Nozioni di base sulla personalizzazione: tensori e operazioni

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza l'origine su GitHub Scarica quaderno

Questo è un tutorial introduttivo su TensorFlow che mostra come:

  • Importa il pacchetto richiesto
  • Crea e usa i tensori
  • Usa l'accelerazione GPU
  • Dimostrare tf.data.Dataset

Importa TensorFlow

Per iniziare, importa il modulo tensorflow . A partire da TensorFlow 2, l'esecuzione desiderosa è attivata per impostazione predefinita. Ciò consente un frontend più interattivo per TensorFlow, i dettagli di cui parleremo molto più avanti.

import tensorflow as tf

Tensori

Un Tensor è un array multidimensionale. Simile agli oggetti NumPy ndarray , gli oggetti tf.Tensor hanno un tipo di dati e una forma. Inoltre, tf.Tensor s può risiedere nella memoria dell'acceleratore (come una GPU). TensorFlow offre una ricca libreria di operazioni ( tf.add , tf.matmul , tf.linalg.inv ecc.) che consumano e producono tf.Tensor s. Queste operazioni convertono automaticamente i tipi Python nativi, 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 tf.Tensor ha una forma e un tipo di dati:

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ù evidenti tra gli array NumPy e tf.Tensor s sono:

  1. I tensori possono essere supportati dalla memoria dell'acceleratore (come GPU, TPU).
  2. I tensori sono immutabili.

Compatibilità NumPy

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

  • Le operazioni di TensorFlow convertono automaticamente i ndarray NumPy in Tensor.
  • Le operazioni NumPy convertono automaticamente i tensor in NumPy ndarray.

I tensori vengono convertiti in modo esplicito in NumPy ndarray utilizzando il loro metodo .numpy() . Queste conversioni sono in genere economiche poiché l'array e tf.Tensor condividono la rappresentazione della memoria sottostante, se possibile. Tuttavia, la condivisione della rappresentazione sottostante non è sempre possibile poiché tf.Tensor può essere ospitato nella memoria della GPU mentre gli array NumPy sono sempre supportati dalla memoria host e la conversione implica una copia dalla GPU alla memoria host.

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 vengono accelerate utilizzando la GPU per il calcolo. Senza alcuna annotazione, TensorFlow decide automaticamente se utilizzare la GPU o la CPU per un'operazione, copiando il tensore tra la CPU e la memoria della GPU, se necessario. I tensori prodotti da un'operazione sono in genere supportati dalla memoria del dispositivo su cui è stata eseguita l'operazione, ad esempio:

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

print("Is there a GPU available: "),
print(tf.config.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 dispositivi

La proprietà Tensor.device fornisce un nome stringa completo del dispositivo che ospita il contenuto del tensore. Questo nome codifica molti dettagli, come un identificatore dell'indirizzo di rete dell'host su cui è in esecuzione questo programma e il dispositivo all'interno di tale host. Ciò è necessario per l'esecuzione distribuita di un programma TensorFlow. La stringa termina con GPU:<N> se il tensore è posizionato sulla N -esima GPU dell'host.

Posizionamento esplicito del dispositivo

In TensorFlow, il posizionamento si riferisce al modo in cui le singole operazioni vengono assegnate (posizionate su) un dispositivo per l'esecuzione. Come accennato, quando non viene fornita alcuna guida esplicita, TensorFlow decide automaticamente quale dispositivo eseguire un'operazione e copia i tensori su quel dispositivo, se necessario. Tuttavia, le operazioni di TensorFlow possono essere posizionate in modo esplicito su dispositivi specifici utilizzando il gestore di contesto tf.device , ad 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.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: 91.47ms
On GPU:
10 loops: 388.16ms

Set di dati

Questa sezione utilizza l' API tf.data.Dataset per creare una pipeline per l'alimentazione dei dati nel modello. L'API tf.data.Dataset viene utilizzata per creare pipeline di input complesse e performanti da parti semplici e riutilizzabili che alimenteranno i cicli di addestramento o valutazione del modello.

Crea un Dataset di dati di origine

Crea un set di dati di origine utilizzando una delle funzioni di fabbrica come Dataset.from_tensors , Dataset.from_tensor_slices o utilizzando oggetti che leggono da file come TextLineDataset o TFRecordDataset . Per ulteriori informazioni, vedere la guida al set di dati TensorFlow .

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 le trasformazioni ai record del set di dati.

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

ds_file = ds_file.batch(2)

Iterare

Gli oggetti tf.data.Dataset supportano l'iterazione per eseguire il loop 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([16  4], shape=(2,), dtype=int32)
tf.Tensor([25 36], 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)