Notions de base de TensorFlow : tenseur, forme, type, sessions et Operajeudi

Qu'est-ce qu'un tenseur ?

Le nom de Tensorflow est directement dérivé de son framework principal : Tensor. Dans Tensorflow, tous les calculs impliquent des tenseurs. Un tenseur est un vecteur ou une matrice à n dimensions qui représente tous les types de données. Toutes les valeurs d'un tenseur contiennent un type de données identique avec une forme connue (ou partiellement connue). La forme des données correspond à la dimensionnalité de la matrice ou du tableau.

Un tenseur peut provenir des données d'entrée ou du résultat d'un calcul. Dans TensorFlow, toutes les opérations sont effectuées dans un graphique. Le graphe est un ensemble de calculs qui s'effectuent successivement. Chaque opération est appelée nœud opérationnel et est connectée les unes aux autres.

Le graphique décrit les opérations et les connexions entre les nœuds. Cependant, il n'affiche pas les valeurs. Le bord des nœuds est le tenseur, c'est-à-dire un moyen de remplir l'opération avec des données.

Dans le Machine Learning, les modèles sont alimentés par une liste d’objets appelés vecteurs de caractéristiques. Un vecteur de caractéristiques peut être de n’importe quel type de données. Le vecteur de caractéristiques sera généralement la principale entrée pour remplir un tenseur. Ces valeurs circuleront dans un nœud opérationnel via le tenseur et le résultat de cette opération/calcul créera un nouveau tenseur qui à son tour sera utilisé dans une nouvelle opération. Toutes ces opérations peuvent être visualisées dans le graphique.

Représentation d'un tenseur

Dans TensorFlow, un tenseur est une collection de vecteurs de caractéristiques (c'est-à-dire un tableau) à n dimensions. Par exemple, si on a une matrice 2×3 avec des valeurs de 1 à 6, on écrit :

Représentation d'un tenseur
Représentation d'un tenseur

TensorFlow représente cette matrice comme :

[[1, 2, 3], 
   [4, 5, 6]]

Si nous créons une matrice tridimensionnelle avec des valeurs de 1 à 8, nous avons :

Représentation d'un tenseur

TensorFlow représente cette matrice comme :

[ [[1, 2],  
       [[3, 4],  
       [[5, 6],  
       [[7,8] ]

Attention: Un tenseur peut être représenté par un scalaire ou peut avoir une forme à plus de trois dimensions. Il est tout simplement plus compliqué de visualiser un niveau de dimension supérieur.

Types de tenseur

Dans TensorFlow, tous les calculs passent par un ou plusieurs tenseurs. Un tf.tensor est un objet avec trois propriétés :

  • Une étiquette unique (nom)
  • Une dimension (forme)
  • Un type de données (dtype)

Chaque opération que vous effectuerez avec TensorFlow implique la manipulation d'un tenseur. Il existe quatre types de tenseurs principaux que vous pouvez créer :

  • tf.Variable
  • tf.constante
  • tf.espace réservé
  • tf.SparseTensor

Dans ce didacticiel, vous apprendrez à créer un tf.constant et un tf.Variable.

Avant de parcourir le didacticiel, assurez-vous d'activer l'environnement conda avec TensorFlow. Nous avons nommé cet environnement hello-tf.

Pour les utilisateurs de MacOS :

source activate hello-tf

Pour Windows utilisateur:

activate hello-tf

Après avoir fait cela, vous êtes prêt à importer Tensorflow

# Import tf
import tensorflow as tf

Créer un tenseur de dimension n

Vous commencez par la création d'un tenseur à une dimension, à savoir un scalaire.

Pour créer un tenseur, vous pouvez utiliser tf.constant() comme indiqué dans l'exemple de forme de tensor TensorFlow ci-dessous :

tf.constant(value, dtype, name = "")
arguments

- `value`: Value of n dimension to define the tensor. Optional
- `dtype`: Define the type of data:    
    - `tf.string`: String variable    
    - `tf.float32`: Float variable    
    - `tf.int16`: Integer variable
- "name": Name of the tensor. Optional. By default, `Const_1:0`

Pour créer un tenseur de dimension 0, exécutez le code suivant

## rank 0
# Default name
r1 = tf.constant(1, tf.int16) 
print(r1)			

Sortie

Tensor("Const:0", shape=(), dtype=int16)

Créer un tenseur de n-dimension

# Named my_scalar
r2 = tf.constant(1, tf.int16, name = "my_scalar") 
print(r2)

Sortie

Tensor("my_scalar:0", shape=(), dtype=int16)

Chaque tenseur est affiché par son nom. Chaque objet tensoriel est défini avec des attributs tensoriels tels qu'une étiquette unique (nom), une dimension (forme) et des types de données TensorFlow (dtype).

Vous pouvez définir un tenseur avec des valeurs décimales ou avec une chaîne en changeant le type de données.

# Decimal
r1_decimal = tf.constant(1.12345, tf.float32)
print(r1_decimal)
# String
r1_string = tf.constant("Guru99", tf.string)
print(r1_string)

Sortie

Tensor("Const_1:0", shape=(), dtype=float32)
Tensor("Const_2:0", shape=(), dtype=string)

Un tenseur de dimension 1 peut être créé comme suit :

## Rank 1r1_vector = tf.constant([1,3,5], tf.int16)
print(r1_vector)
r2_boolean = tf.constant([True, True, False], tf.bool)
print(r2_boolean)

Sortie

Tensor("Const_3:0", shape=(3,), dtype=int16)
Tensor("Const_4:0", shape=(3,), dtype=bool)

Vous pouvez remarquer que la forme TensorFlow n'est composée que d'une seule colonne.

Pour créer un tableau de 2 dimensions tensorielles, vous devez fermer les parenthèses après chaque ligne. Consultez l'exemple de forme Keras Tensor ci-dessous

## Rank 2
r2_matrix = tf.constant([ [1, 2],
                          [3, 4] ],tf.int16)
print(r2_matrix)

Sortie

Tensor("Const_5:0", shape=(2, 2), dtype=int16)

La matrice comporte 2 lignes et 2 colonnes remplies de valeurs 1, 2, 3, 4.

Une matrice à 3 dimensions est construite en ajoutant un autre niveau avec les parenthèses.

## Rank 3
r3_matrix = tf.constant([ [[1, 2],
                           [3, 4], 
                           [5, 6]] ], tf.int16)
print(r3_matrix)

Sortie

Tensor("Const_6:0", shape=(1, 3, 2), dtype=int16)

La matrice ressemble à la photo deux.

Forme du tenseur

Lorsque vous imprimez un tenseur, TensorFlow devine la forme. Cependant, vous pouvez obtenir la forme du tenseur avec la propriété de forme TensorFlow.

Ci-dessous, vous construisez une matrice remplie d'un nombre de 10 à 15 et vous vérifiez la forme de m_shape

# Shape of tensor
m_shape = tf.constant([ [10, 11],
                        [12, 13],
                        [14, 15] ]                      
                     ) 
m_shape.shape

Sortie

TensorShape([Dimension(3), Dimension(2)])

La matrice comporte 3 lignes et 2 colonnes.

TensorFlow dispose de commandes utiles pour créer un vecteur ou une matrice remplie de 0 ou 1. Par exemple, si vous souhaitez créer un tenseur 1D avec une forme spécifique de 10, rempli de 0, vous pouvez exécuter le code ci-dessous :

# Create a vector of 0
print(tf.zeros(10))

Sortie

Tensor("zeros:0", shape=(10,), dtype=float32)

La propriété fonctionne également pour la matrice. Ici, vous créez une matrice 10×10 remplie de 1

# Create a vector of 1
print(tf.ones([10, 10]))

Sortie

Tensor("ones:0", shape=(10, 10), dtype=float32)

Vous pouvez utiliser la forme d'une matrice donnée pour créer un vecteur de uns. La matrice m_shape est de dimensions 3×2. Vous pouvez créer un tenseur avec 3 lignes remplies par une avec le code suivant :

# Create a vector of ones with the same number of rows as m_shape
print(tf.ones(m_shape.shape[0]))

Sortie

Tensor("ones_1:0", shape=(3,), dtype=float32)

Si vous passez la valeur 1 entre parenthèses, vous pouvez construire un vecteur de uns égal au nombre de colonnes dans la matrice m_shape.

# Create a vector of ones with the same number of column as m_shape
print(tf.ones(m_shape.shape[1]))

Sortie

Tensor("ones_2:0", shape=(2,), dtype=float32)

Enfin, vous pouvez créer une matrice 3×2 avec un seul

print(tf.ones(m_shape.shape))

Sortie

Tensor("ones_3:0", shape=(3, 2), dtype=float32)

Type de données

La deuxième propriété d'un tenseur est le type de données. Un tenseur ne peut avoir qu'un seul type de données à la fois. Un tenseur ne peut avoir qu'un seul type de données. Vous pouvez renvoyer le type avec la propriété dtype.

print(m_shape.dtype)

Sortie

<dtype: 'int32'>

Dans certains cas, vous souhaitez modifier le type de données. Dans TensorFlow, c'est possible avec la méthode tf.cast.

Exemple

Ci-dessous, un tenseur flottant est converti en entier en utilisant la méthode cast.

# Change type of data
type_float = tf.constant(3.123456789, tf.float32)
type_int = tf.cast(type_float, dtype=tf.int32)
print(type_float.dtype)
print(type_int.dtype)

Sortie

<dtype: 'float32'>
<dtype: 'int32'>

TensorFlow choisit automatiquement le type de données lorsque l'argument n'est pas spécifié lors de la création du tenseur. TensorFlow devinera quels sont les types de données les plus probables. Par exemple, si vous transmettez un texte, il devinera qu'il s'agit d'une chaîne et le convertira en chaîne.

Opérateur de création

Quelques opérateurs TensorFlow utiles

Vous savez créer un tenseur avec TensorFlow. Il est temps d'apprendre à effectuer des opérations mathématiques.

TensorFlow contient toutes les opérations de base. Vous pouvez commencer par un simple. Vous utiliserez la méthode TensorFlow pour calculer le carré d'un nombre. Cette opération est simple car un seul argument est nécessaire pour construire le tenseur.

Le carré d'un nombre est construit avec tf.sqrt(x) avec x comme nombre flottant.

x = tf.constant([2.0], dtype = tf.float32)
print(tf.sqrt(x))

Sortie

Tensor("Sqrt:0", shape=(1,), dtype=float32)

Attention: La sortie a renvoyé un objet tenseur et non le résultat du carré de 2. Dans l'exemple, vous imprimez la définition du tenseur et non l'évaluation réelle de l'opération. Dans la section suivante, vous apprendrez comment TensorFlow fonctionne pour exécuter les opérations.

Voici une liste des opérations couramment utilisées. L'idée est la même. Chaque opération nécessite un ou plusieurs arguments.

  • tf.ajouter(a, b)
  • tf.substract(a, b)
  • tf.multiplier (a, b)
  • tf.div(a, b)
  • tf.pow(a, b)
  • tf.exp(a)
  • tf.sqrt(a)

Exemple

# Add
tensor_a = tf.constant([[1,2]], dtype = tf.int32)
tensor_b = tf.constant([[3, 4]], dtype = tf.int32)

tensor_add = tf.add(tensor_a, tensor_b)print(tensor_add)

Sortie

Tensor("Add:0", shape=(1, 2), dtype=int32)

Explication du code

Créez deux tenseurs :

  • un tenseur avec 1 et 2
  • un tenseur avec 3 et 4

Vous additionnez les deux tenseurs.

Avertissement: que les deux tenseurs doivent avoir la même forme. Vous pouvez exécuter une multiplication sur les deux tenseurs.

# Multiply
tensor_multiply = tf.multiply(tensor_a, tensor_b)
print(tensor_multiply)

Sortie

Tensor("Mul:0", shape=(1, 2), dtype=int32)

Variables

Jusqu'à présent, vous n'avez créé que des tenseurs constants. Ce n'est pas d'une grande utilité. Les données arrivent toujours avec des valeurs différentes, pour capturer cela, vous pouvez utiliser la classe Variable. Il représentera un nœud où les valeurs changent toujours.

Pour créer une variable, vous pouvez utiliser la méthode tf.get_variable()

tf.get_variable(name = "", values, dtype, initializer)
argument
- `name = ""`: Name of the variable
- `values`: Dimension of the tensor
- `dtype`: Type of data. Optional
- `initializer`: How to initialize the tensor. Optional
If initializer is specified, there is no need to include the `values` as the shape of `initializer` is used.

Par exemple, le code ci-dessous crée une variable bidimensionnelle avec deux valeurs aléatoires. Par défaut, TensorFlow renvoie une valeur aléatoire. Vous nommez la variable var

# Create a Variable
## Create 2 Randomized values
var = tf.get_variable("var", [1, 2])
print(var.shape)

Sortie

(1, 2)

Dans le deuxième exemple, vous créez une variable avec une ligne et deux colonnes. Vous devez utiliser [1,2] pour créer la dimension de la variable

Les valeurs initiales de ce tenseur sont nulles. Par exemple, lorsque vous entraînez un modèle, vous devez disposer de valeurs initiales pour calculer le poids des fonctionnalités. Ci-dessous, vous définissez ces valeurs initiales sur zéro.

var_init_1 = tf.get_variable("var_init_1", [1, 2], dtype=tf.int32,  initializer=tf.zeros_initializer)
print(var_init_1.shape)

Sortie

(1, 2)

Vous pouvez transmettre les valeurs d'un tenseur constant dans une variable. Vous créez un tenseur constant avec la méthode tf.constant(). Vous utilisez ce tenseur pour initialiser la variable.

Les premières valeurs de la variable sont 10, 20, 30 et 40. Le nouveau tenseur aura une forme de 2×2.

# Create a 2x2 matrixtensor_const = tf.constant([[10, 20],
[30, 40]])
# Initialize the first value of the tensor equals to tensor_const
var_init_2 = tf.get_variable("var_init_2", dtype=tf.int32,  initializer=tensor_const)
print(var_init_2.shape)

Sortie

(2, 2)

placeholder

Un espace réservé a pour but d'alimenter le tenseur. L'espace réservé est utilisé pour initialiser les données à circuler à l'intérieur des tenseurs. Pour fournir un espace réservé, vous devez utiliser la méthode feed_dict. L'espace réservé sera alimenté uniquement au cours d'une session.

Dans l'exemple suivant, vous verrez comment créer un espace réservé avec la méthode tf.placeholder. Dans la prochaine session, vous apprendrez à alimenter un espace réservé avec une valeur tensorielle réelle.

La syntaxe est:

tf.placeholder(dtype,shape=None,name=None )
arguments:
- `dtype`: Type of data
- `shape`: dimension of the placeholder. Optional. By default, shape of the data
- `name`: Name of the placeholder. Optional			
data_placeholder_a = tf.placeholder(tf.float32, name = "data_placeholder_a")
print(data_placeholder_a)

Sortie

Tensor("data_placeholder_a:0", dtype=float32)

Session

TensorFlow fonctionne autour de 3 composants principaux :

  • Graphique
  • tenseur
  • Session
Composants DESCRITPTION
Graphique Le graphique est fondamental dans TensorFlow. Toutes les opérations mathématiques (ops) sont effectuées à l'intérieur d'un graphique. Vous pouvez imaginer un graphique comme un projet où toutes les opérations sont effectuées. Les nœuds représentent ces opérations, ils peuvent absorber ou créer de nouveaux tenseurs.
tenseur Un tenseur représente les données qui progressent entre les opérations. Vous avez vu précédemment comment initialiser un tenseur. La différence entre une constante et une variable réside dans le fait que les valeurs initiales d'une variable changeront avec le temps.
Session Une session exécutera l'opération à partir du graphique. Pour alimenter le graphique avec les valeurs d'un tenseur, vous devez ouvrir une session. Dans une session, vous devez exécuter un opérateur pour créer une sortie.

Les graphiques et les sessions sont indépendants. Vous pouvez exécuter une session et obtenir les valeurs à utiliser ultérieurement pour des calculs ultérieurs.

Dans l'exemple ci-dessous, vous allez :

  • Créer deux tenseurs
  • Créer une opération
  • Ouvrir une session
  • Imprimer le résultat

Étape 1) Vous créez deux tenseurs x et y

## Create, run  and evaluate a session
x = tf.constant([2])
y = tf.constant([4])

Étape 2) Vous créez l'opérateur en multipliant x et y

## Create operator
multiply = tf.multiply(x, y)

Étape 3) Vous ouvrez une session. Tous les calculs auront lieu au cours de la session. Lorsque vous avez terminé, vous devez fermer la session.

## Create a session to run the code
sess = tf.Session()result_1 = sess.run(multiply)
print(result_1)
sess.close()

Sortie

[8]

Explication du code

  • tf.Session() : ouvre une session. Toutes les opérations se dérouleront au sein des sessions
  • run(multiply) : exécute l'opération créée à l'étape 2.
  • print(result_1) : Enfin, vous pouvez imprimer le résultat
  • close() : Ferme la session

Le résultat montre 8, qui est la multiplication de x et y.

Une autre façon de créer une session consiste à l'intérieur d'un bloc. L'avantage est qu'il ferme automatiquement la session.

with tf.Session() as sess:    
result_2 = multiply.eval()
print(result_2)

Sortie

[8]

Dans un contexte de session, vous pouvez utiliser la méthode eval() pour exécuter l'opération. C'est équivalent à run(). Cela rend le code plus lisible.

Vous pouvez créer une session et voir les valeurs à l'intérieur des tenseurs que vous avez créés jusqu'à présent.

## Check the tensors created before
sess = tf.Session()
print(sess.run(r1))
print(sess.run(r2_matrix))
print(sess.run(r3_matrix))

Sortie

1
[[1 2] 
 [3 4]]
[[[1 2]  
  [3 4]  
  [5 6]]]

Les variables sont vides par défaut, même après avoir créé un tenseur. Vous devez initialiser la variable si vous souhaitez utiliser la variable. L'objet tf.global_variables_initializer() doit être appelé pour initialiser les valeurs d'une variable. Cet objet initialisera explicitement toutes les variables. Ceci est utile avant d’entraîner un modèle.

Vous pouvez vérifier les valeurs des variables que vous avez créées auparavant. Notez que vous devez utiliser run pour évaluer le tenseur

sess.run(tf.global_variables_initializer())
print(sess.run(var))
print(sess.run(var_init_1))
print(sess.run(var_init_2))

Sortie

[[-0.05356491  0.75867283]]
[[0 0]]
[[10 20] 
 [30 40]]

Vous pouvez utiliser l'espace réservé que vous avez créé auparavant et l'alimenter avec la valeur réelle. Vous devez transmettre les données dans la méthode feed_dict.

Par exemple, vous prendrez la puissance 2 de l'espace réservé data_placeholder_a.

import numpy as np
power_a = tf.pow(data_placeholder_a, 2)
with tf.Session() as sess:  
data = np.random.rand(1, 10)  
print(sess.run(power_a, feed_dict={data_placeholder_a: data}))  # Will succeed.

Explication du code

  • importer numpy en tant que np : importer bibliothèque numpy pour créer les données
  • tf.pow (data_placeholder_a, 2) : créer les opérations
  • np.random.rand(1, 10) : créer un tableau aléatoire de données
  • feed_dict={data_placeholder_a: data} : Alimenter l'espace réservé avec des données

Sortie

[[0.05478134 0.27213147 0.8803037  0.0398424  0.21172127 0.01444725  0.02584014 0.3763949  0.66022706 0.7565559 ]]

Graphique

TensorFlow dépend d'une approche géniale pour restituer l'opération. Tous les calculs sont représentés avec un schéma de flux de données. Le graphique de flux de données a été développé pour veiller aux dépendances des données entre les opérations individuelles. Une formule mathématique ou un algorithme est constitué d'un certain nombre d'opérations successives. Un graphique est un moyen pratique de visualiser la façon dont les calculs sont coordonnés.

Le graphique montre un nœud et le bord. Le nœud est la représentation d'une opération, c'est à dire l'unité de calcul. L'arête est le tenseur, elle peut produire un nouveau tenseur ou consommer les données d'entrée. Cela dépend des dépendances entre les opérations individuelles.

La structure du graphe relie les opérations (c'est-à-dire les nœuds) et la façon dont ces opérations sont alimentées. Notez que le graphique n'affiche pas le résultat des opérations, il permet uniquement de visualiser le lien entre les opérations individuelles.

Voyons un exemple.

Imaginez que vous souhaitiez évaluer la fonction suivante :

Graphique

TensorFlow créera un graphique pour exécuter la fonction. Le graphique ressemble à ceci :

Exemple de graphique TensorFlow

Exemple de graphique TensorFlow

Vous pouvez facilement voir le chemin que prendront les tenseurs pour atteindre la destination finale.

Par exemple, vous pouvez voir que l'opération add ne peut pas être effectuée avant et . Le graphique explique que cela :

  1. calculer et :
  2. ajouter 1) ensemble
  3. ajouter à 2)
  4. ajouter 3) à
x = tf.get_variable("x", dtype=tf.int32,  initializer=tf.constant([5]))
z = tf.get_variable("z", dtype=tf.int32,  initializer=tf.constant([6]))
c = tf.constant([5], name =	"constant")square = tf.constant([2], name =	"square")
f = tf.multiply(x, z) + tf.pow(x, square) + z + c

Explication du code

  • x : initialise une variable appelée x avec une valeur constante de 5
  • z : Initialiser une variable appelée z avec une valeur constante de 6
  • c : Initialiser un tenseur constant appelé c avec une valeur constante de 5
  • carré : initialise un tenseur constant appelé carré avec une valeur constante de 2
  • f : Construire l'opérateur

Dans cet exemple, nous choisissons de garder les valeurs des variables fixes. Nous avons également créé un tenseur constant appelé c qui est le paramètre constant de la fonction f. Il prend une valeur fixe de 5. Dans le graphique, vous pouvez voir ce paramètre dans le tenseur appelé constante.

Nous avons également construit un tenseur constant pour la puissance dans l'opérateur tf.pow(). Ce n'est pas nécessaire. Nous l'avons fait pour que vous puissiez voir le nom du tenseur dans le graphique. C'est le cercle appelé carré.

À partir du graphique, vous pouvez comprendre ce qui se passera avec les tenseurs et comment ils peuvent renvoyer une sortie de 66.

Le code ci-dessous évalue la fonction dans une session.

init = tf.global_variables_initializer() # prepare to initialize all variables
with tf.Session() as sess:    
	init.run() # Initialize x and y    
    function_result = f.eval()
print(function_result)

Sortie

[66]

Résumé

TensorFlow fonctionne autour de :

  • Graphique: Environnement informatique contenant les opérations et les tenseurs
  • Tenseurs: Représente les données (ou la valeur) qui circuleront dans le graphique. C'est le bord du graphique
  • Sessions: Permettre l'exécution des opérations

Créer un tenseur constant

constant objet
D0 tf.constant(1, tf.int16)
D1 tf.constant([1,3,5], tf.int16)
D2 tf.constant([ [1, 2], [3, 4] ],tf.int16)
D3 tf.constant([ [[1, 2],[3, 4], [5, 6]] ], tf.int16)

Créer un opérateur

Créer un opérateur Exlcusion
a + b tf.ajouter(a, b)
a * b tf.multiplier (a, b)

Créer un tenseur variable

Créer une variable objet
valeur aléatoire tf.get_variable("var", [1, 2])
première valeur initialisée tf.get_variable("var_init_2", dtype=tf.int32, initializer=[ [1, 2], [3, 4] ])

Ouvrir une session

Session objet
Créer une séance tf.Session()
Exécuter une session tf.Session.run()
Évaluer un tenseur nom_variable.eval()
Fermer une session session.close()
Séance par bloc avec tf.Session() comme session :