Come creare un tensore su Pytorch: differenze tra le versioni

Da Wiki AI.
Nessun oggetto della modifica
Nessun oggetto della modifica
 
(10 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
 
== Approcci di Inizializzazione ==
 
Esistono vari approcci per creare da zero un [[Tensore]] con [[PyTorch]], ne elenchiamo alcuni dei più semplici:
Esistono vari approcci per creare da zero un [[Tensore]] con [[PyTorch]], ne elenchiamo alcuni dei più semplici:


Riga 10: Riga 9:
* <code>torch.rand()</code>: Inizializza un tensore con valori casuali compresi tra 0 e 1 da una distribuzione uniforme.
* <code>torch.rand()</code>: Inizializza un tensore con valori casuali compresi tra 0 e 1 da una distribuzione uniforme.


== Esempi di Inizializzazione ==
''[https://colab.research.google.com/drive/18_EtkPURM2rBx5KQ4TEpMvz6bT6La17h?usp=sharing 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.
Facciamo un esempio minimale che adotti il primo approccio: torch.ones.


'''''1.'''''    Il primo step è importare la libreria torch:
'''''1.'''''    Il primo step è importare la libreria torch:
Riga 18: Riga 18:
<code>import torch</code>
<code>import torch</code>


'''''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:
<code>torch.ones((2,3))</code>
''[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]''
[[File:Tensore 1.png|miniatura|396x396px]]
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:
<code>torch.ones((2,3)), dtype=torch.int8)</code>
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:
<code>torch.full((2,3), 54,47279)</code>
Se vogliamo che gli elementi del tensore siano estratti casualmente da un intervallo a nostra scelta (ad esempio [0, 100]) possiamo eseguire:
<code>torch.randint(0, 100, (2,3)</code>
Quindi specificando gli estremi dell'intervallo PRIMA di definire le dimensioni del tensore.
== Abilitiamo il tensore al calcolo dei [[Gradienti di ottimizzazione|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:
<code>torch.full((2, 3) 4., requires_grad=True)</code>
[[File:Tensore con gradienti.png|miniatura|425x425px]]
''[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:
<code>x=torch.full((2, 3) 4., requires_grad=True)</code>
Ora creiamo la nostra variabile y che è di fatto un secondo tensore che è legato al primo tensore x tramite la seguente relazione:
<code>y=2*x+3</code>
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:
[[File:Tensore y.png|miniatura|454x454px]]
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:
<code>y.backward(torch.ones_like(x))</code>
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: <code>torch.ones_like(x)</code>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.
[[File:Tensorino.png|miniatura|498x498px]]
Per visualizzare questo nuovo tensore esegui:
<code>x.grad</code>
E finalmente visualizziamo i nostri gradienti! In questo sono tutti 2 il che ha senso perchè:
x=4 -> y=11


'''''2.'''''    Inizializziamo 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:  
Se cambio x di una singola unità ottengo che:


<code>torch.ones((2,3))</code> 
x=5 -> y=13


e 13 - 11 = 2


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


[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] 
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!


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


tensor([[1., 1., 1.], 


[1., 1., 1.]])


#




Riga 41: Riga 116:




Fonte: PyTorch Artificial Intelligence Fundamentals by Jibin Mathew
Fonte: [https://discordapp.com/channels/1205124047931703306/1205156557285892116/1217016623202963506 PyTorch Artificial Intelligence Fundamentals by Jibin Mathew]
[[Categoria:Tutorial]]
[[Categoria:Tutorial]]

Versione attuale delle 16:52, 12 mar 2024

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