Come creare un tensore su Pytorch

Da Wiki AI.

Approcci di Inizializzazione

Esistono vari approcci per creare da zero un Tensore con PyTorch, ne elenchiamo alcuni dei più semplici:

  • torch.ones(): Metodo che inizializza (= crea e assegna valori iniziali ad..) un tensore, impostando tutti gli elementi uguali a 1. è molto comune nello sviluppo di reti neurali poiché spesso di procede settando i pesi della rete a valori iniziali uguali.
  • torch.zeros(): Simile a torch.ones(), ma inizializza tutti gli elementi del tensore a 0.
  • torch.empty(): Crea un tensore non inizializzato, quindi i valori possono essere qualsiasi cosa.
  • torch.randn(): Inizializza un tensore con valori casuali presi da una distribuzione normale (media 0, deviazione standard 1).
  • torch.rand(): Inizializza un tensore con valori casuali compresi tra 0 e 1 da una distribuzione uniforme.

Esempi di Inizializzazione

Qui trovi un Colab dove puoi provare queste righe di codice e vederne il funzionamento te stess*!

Innanzitutto facciamo un esempio minimale che adotti il primo approccio: torch.ones.

1. Il primo step è importare la libreria torch:

import torch

2. Ora possiamo inizializzare il tensore specificando il numero di righe e il numero di colonne che vogliamo abbia il nostro tensore di tutti uno, in questo caso rispettivamente 2 e 3:

torch.ones((2,3))

[n.b. Essendo le dimensioni in questo caso due, si può parlare di un tipo specifico di Tensore detto Matrice. Se la dimensione fosse una si tratterebbe di un Vettore. Dalle tre dimensioni in su si definiscono genericamente Tensori]

L'inizializzazione del tensore con questa riga di codice lo stampa anche in automatico! In questo caso quindi visualizzeremo questo:

Abbiamo inizializzato il tensore!

Personalizziamo l'inizializzazione

Possiamo notare che il formato dati assegnato di default è di numero decimale (float). Se vogliamo ad esempio che gli elementi del Tensore siano dei numeri interi (int) possiamo specificarlo (insieme dalla dimensione del formato dati, 8, 16, 32 bit ecc.) nella riga di inizializzazione in questo modo:

torch.ones((2,3)), dtype=torch.int8)


Se vogliamo che gli elementi nel tensore abbiano comunque tutti lo stesso valore ma vogliamo decidere noi quale valore in particolare, possiamo eseguire ad esempio:

torch.full((2,3), 54,47279)

Se vogliamo che gli elementi del tensore siano estratti casualmente da un intervallo a nostra scelta (ad esempio [0, 100]) possiamo eseguire:

torch.randint(0, 100, (2,3)

Quindi specificando gli estremi dell'intervallo PRIMA di definire le dimensioni del tensore.

Abilitiamo il tensore al calcolo dei gradienti

Possiamo fare in modo che quando si eseguono operazioni che coinvolgono questo tensore, PyTorch tracci automaticamente le operazioni effettuate e calcoli in automatico il gradiente di una funzione x (tendenzialmente è la Funzione Obiettivo (loss)) rispetto ai valori nel tensore.

Facciamo un esempio!

Inizializziamo un Tensore, riempiamolo di 4. e aggiungiamo la variabile requires_grad:

torch.full((2, 3) 4., requires_grad=True)

[n.b. Solo tensori contenenti valori di tipo float o complex possono richiedere il calcolo dei gradienti]


Otteniamo il seguente tensore:


Assegniamo il tensore ad una variabile x:

x=torch.full((2, 3) 4., requires_grad=True)

Ora creiamo la nostra variabile y che è di fatto un secondo tensore che è legato al primo tensore x tramite la seguente relazione:

y=2*x+3

Noi per fortuna ci rendiamo la vita facile e partiamo da un tensore x di tutti 4, quindi sappiamo già che i valori nel secondo tensore y saranno tutti:

y = 2*4 + 3 = 11

E infatti stampando y vediamo:

Possiamo notare che dove prima c'era scritto requires_grad, ora troviamo l'attributo "grad_fn=<AddBackward0>", ma cosa significa?

"grad_fn" è un attributo di autograd sta per Gradient function, e che indica che PyTorch ha registrato questa operazione (la moltiplicazione per 2 e l'aggiunta di 3) in modo che il gradiente possa essere calcolato durante la backpropagation.


Come lo visualizziamo questo gradiente?

Basta eseguire:

y.backward(torch.ones_like(x))

Con questa riga andiamo a chiedere a PyTorch di calcolare i gradienti di y rispetto ad x. Se sei stat* attent* riconoscerai la formulazione torch.ones, che serve ad inizializzare un tensore di tutti uno. Qui troviamo la variazione: torch.ones_like(x)che imposta le dimensioni del tensore come quelle del tensore x. Quello che stiamo facendo è creare un tensore nuovo per visualizzare i gradienti di y rispetto ad x.

Per visualizzare questo nuovo tensore esegui:

x.grad


E finalmente visualizziamo i nostri gradienti! In questo sono tutti 2 il che ha senso perchè:

x=4 -> y=11

Se cambio x di una singola unità ottengo che:

x=5 -> y=13

e 13 - 11 = 2

Dunque un cambiamento unitario di x risulta in un cambiamento di 2 in y!

Il gradiente non è altro che la pendenza della retta che rappresenta la relazione tra la variazione di x e la variazione di y: la derivata di y!






Fonte: PyTorch Artificial Intelligence Fundamentals by Jibin Mathew