Basi di customizzazione: tensori e operazioni

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza il sorgente su GitHub Scarica il notebook

Questo è un tutorial introduttivo su TensorFlow che mostra come:

  • Importare i pacchetti richiesti
  • Creare e usare tensori
  • Usare l'accelerazione GPU
  • Dare una dimostrazione del tf.data.Dataset
from __future__ import absolute_import, division, print_function

try:
  # %tensorflow_version only exists in Colab.
  %tensorflow_version 2.x
except Exception:
  pass

Importare TensorFlow

Per iniziare, importa il modulo tensorflow. A partire da TensorFlow 2.0, l'esecuzione eager è attiva di default. Questo permette un frontend più interattivo verso TensorFlow, di cui i dettagli verranno discussi oltre.

import tensorflow as tf

Tensori

Un Tensore è un array multi-dimensionale. Come negli oggetti ndarray di NumPy, gli oggetti tf.Tensor hanno un tipo di dato e un formato. Inoltre, gli oggetti tf.Tensor possono risiedere in un acceleratore di memoria (come una GPU). TensorFlow offre una libreria ricca di operazioni (tf.add, tf.matmul, tf.linalg.inv etc.) che consumano e producono oggetti tf.Tensor. Queste operazioni convertono automaticamente tipi nativi di Python, ad esempio:

print(tf.add(1, 2))
print(tf.add([1, 2], [3, 4]))
print(tf.square(5))
print(tf.reduce_sum([1, 2, 3]))

# Operator overloading is also supported
print(tf.square(2) + tf.square(3))
tf.Tensor(3, shape=(), dtype=int32)
tf.Tensor([4 6], shape=(2,), dtype=int32)
tf.Tensor(25, shape=(), dtype=int32)
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(13, shape=(), dtype=int32)

Ogni oggetto tf.Tensor ha una forma e un tipo di dato:

x = tf.matmul([[1]], [[2, 3]])
print(x)
print(x.shape)
print(x.dtype)
tf.Tensor([[2 3]], shape=(1, 2), dtype=int32)
(1, 2)
<dtype: 'int32'>

Le differenze più ovvie tra gli array NumPy e i tf.Tensor sono:

  1. I tensori possono essere supportati da acceleratori di memoria (come GPU, TPU).
  2. I tensori sono immutabili.

Compatibilità con NumPy

La conversione tra oggetti tf.Tensor di TensorFlow e un ndarray di NumPy è facile:

  • Le operazioni di TensorFlow convertono automaticamente gli ndarrays di NumPy in tensori.
  • Le operazioni di NumPy convertono automaticamente i tensors a ndarrays di NumPy. appresentazione di memoria, se possible I tensori sono convertiti esplicitamente in ndarrays di NumPy usando il loro metodo. Queste conversioni sono tipicamente efficienti dal momento che l'array e tf.Tensor condividono, se possibile, la stessa rappresentazione di memoria. Tuttavia, condividere la rappresentazione di memoria sottostante non è sempre possibile dal momento che tf.Tensor può essere allocata nella memoria GPU mentre gli array NumPy sono sempre ospitati nella memoria, e la conversione coinvolge una copia dalla GPU alla memoria centrale e mentre gli array numPy sono sempre protetti dalla memoria.
import numpy as np

ndarray = np.ones([3, 3])

print("TensorFlow operations convert numpy arrays to Tensors automatically")
tensor = tf.multiply(ndarray, 42)
print(tensor)


print("And NumPy operations convert Tensors to numpy arrays automatically")
print(np.add(tensor, 1))

print("The .numpy() method explicitly converts a Tensor to a numpy array")
print(tensor.numpy())
TensorFlow operations convert numpy arrays to Tensors automatically
tf.Tensor(
[[42. 42. 42.]
 [42. 42. 42.]
 [42. 42. 42.]], shape=(3, 3), dtype=float64)
And NumPy operations convert Tensors to numpy arrays automatically
[[43. 43. 43.]
 [43. 43. 43.]
 [43. 43. 43.]]
The .numpy() method explicitly converts a Tensor to a numpy array
[[42. 42. 42.]
 [42. 42. 42.]
 [42. 42. 42.]]

Accelerazione GPU

Molte operazioni di TensorFlow sono accelerate usando la GPU per la computazione. In assenza di indicazioni, TensorFlow decide automaticamente se usare la GPU o la CPU per un'operazione—copiando il tensore tra la memoria della CPU e quella della GPU se necessario. I Tensori prodotti da un'operazione sono tipicamente supportate dalla memoria del dispositivo su cui l'operazione è stata eseguito, per esempio:

x = tf.random.uniform([3, 3])

print("Is there a GPU available: "),
print(tf.config.experimental.list_physical_devices("GPU"))

print("Is the Tensor on GPU #0:  "),
print(x.device.endswith('GPU:0'))
Is there a GPU available: 
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
Is the Tensor on GPU #0:  
True

Nomi dei Device

La proprietà Tensor.device fornisce una stringa interamente qualificata con il nome del dispositivo che ospita il contenuto del tensore. Questo nome codifica molti dettagli, tra cui un identificativo dell'indirizzo di rete dell'host su cui il programma è in esecuzione e il device dentro quel host. Questo è richiesto per l'esecuzione distribuita di un programma TensorFlow. La stringa termina con GPU:<N> se il tensore è allocato nel N-esimo GPU del host.

Placement esplicito su un Device

In TensorFlow, il termine placement si refersce a come operazioni individuali sono assegnate a un dispositivo per l'esecuzione. Come menzionato, quando non è fornita un'istruzione esplicita fornita, TensorFlow decide automaticamente su quale device eseguire un'operazione e copia il tensore su quel device se necessario. Tuttavia le operazione di TensorFlow possono essere esplicitamente assegnati a specifici dispositivi usando il context manager tf.device, per esempio:

import time

def time_matmul(x):
  start = time.time()
  for loop in range(10):
    tf.matmul(x, x)

  result = time.time()-start

  print("10 loops: {:0.2f}ms".format(1000*result))

# Force execution on CPU
print("On CPU:")
with tf.device("CPU:0"):
  x = tf.random.uniform([1000, 1000])
  assert x.device.endswith("CPU:0")
  time_matmul(x)

# Force execution on GPU #0 if available
if tf.config.experimental.list_physical_devices("GPU"):
  print("On GPU:")
  with tf.device("GPU:0"): # Or GPU:1 for the 2nd GPU, GPU:2 for the 3rd etc.
    x = tf.random.uniform([1000, 1000])
    assert x.device.endswith("GPU:0")
    time_matmul(x)
On CPU:
10 loops: 98.34ms
On GPU:
10 loops: 232.94ms

Datasets

Questa sezione usa la API tf.data.Dataset per costruire una pipeline per fornire i dati al tuo modello. L'API tf.data.Dataset è usata per costruire pipeline di input complesse e performanti a partire da pezzi semplici e riutilizzabili che saranno dati in pasto ai loop di addestramento o valutazione del tuo modello.

Creare un Dataset sorgente

Crea un dataset sorgente usando una delle funzioni factory come Dataset.from_tensors, Dataset.from_tensor_slices, o usando oggetti che leggono da file come TextLineDataset o TFRecordDataset. Vedi la guida dei TensorFlow Dataset per ulteriori informazioni.

ds_tensors = tf.data.Dataset.from_tensor_slices([1, 2, 3, 4, 5, 6])

# Create a CSV file
import tempfile
_, filename = tempfile.mkstemp()

with open(filename, 'w') as f:
  f.write("""Line 1
Line 2
Line 3
  """)

ds_file = tf.data.TextLineDataset(filename)

Applicare trasformazioni

Usa le funzioni di trasformazione come map, batch, e shuffle per applicare trasformazioni sui record del dataset.

ds_tensors = ds_tensors.map(tf.square).shuffle(2).batch(2)

ds_file = ds_file.batch(2)

Iterare

Gli oggetti tf.data.Dataset supportano le iterazioni per ciclare sui record:

print('Elements of ds_tensors:')
for x in ds_tensors:
  print(x)

print('\nElements in ds_file:')
for x in ds_file:
  print(x)
Elements of ds_tensors:
tf.Tensor([1 9], shape=(2,), dtype=int32)
tf.Tensor([ 4 25], shape=(2,), dtype=int32)
tf.Tensor([36 16], shape=(2,), dtype=int32)

Elements in ds_file:
tf.Tensor([b'Line 1' b'Line 2'], shape=(2,), dtype=string)
tf.Tensor([b'Line 3' b'  '], shape=(2,), dtype=string)