Nozioni di base sulla personalizzazione: tensori e operazioni

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza la fonte su GitHub Scarica il taccuino

Questo è un tutorial introduttivo a TensorFlow che mostra come:

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

Importa flusso tensore

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

import tensorflow as tf

tensori

Un tensore è un array multidimensionale. Simile agli oggetti NumPy ndarray , tf.Tensor oggetti tf.Tensor hanno un tipo di dati e una forma. Inoltre, i tf.Tensor possono 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 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 narray NumPy in Tensor.
  • Le operazioni NumPy convertono automaticamente i tensori in NumPy ndarray.

I tensori vengono esplicitamente convertiti in NumPy ndarray usando il loro metodo .numpy() . Queste conversioni sono generalmente 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 dell'host e la conversione comporta una copia dalla GPU alla memoria dell'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 memoria della CPU e 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 quell'host. Ciò è necessario per l'esecuzione distribuita di un programma TensorFlow. Le estremità della stringa con GPU:<N> se il tensore viene posizionato sul N GPU -esimo sull'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 una 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: 93.77ms
On GPU:
10 loops: 397.49ms

Set di dati

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

Crea un Dataset 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 TensorFlow Dataset .

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

tf.data.Dataset oggettitf.data.Dataset supportano l'iterazione per eseguire il ciclo 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([4 9], shape=(2,), dtype=int32)
tf.Tensor([ 1 16], 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)