Machine Learning Academy · Lezione

Tensori PyTorch: creazione, operazioni e trasferimento alla GPU

Imparerete a creare tensori da liste Python e array NumPy, eseguire operazioni elemento per elemento e matriciali e trasferire i tensori sulla GPU con .to('cuda').

Lezione 1 di 413 passaggi

Tensori PyTorch: creazione, operazioni e trasferimento alla GPU è una lezione Machine Learning Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Machine Learning Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Machine Learning Academy include 4 lezioni in totale.

Che cos’è un tensore PyTorch

Un tensore è la struttura dati fondamentale di PyTorch: essenzialmente un array n-dimensionale simile a un array NumPy, ma con supporto GPU integrato e differenziazione automatica. I tensori possono essere scalari (0D), vettori (1D), matrici (2D) o strutture con più dimensioni. I tensori di PyTorch tengono traccia della cronologia dei calcoli, rendendo possibile il calcolo automatico dei gradienti per l’addestramento delle reti neurali.

import torch

# Scalar (0-dimensional tensor)
scalar = torch.tensor(3.14)
print(scalar.shape)   # torch.Size([])

# Vector (1D)
vector = torch.tensor([1.0, 2.0, 3.0])
print(vector.shape)   # torch.Size([3])

# Matrix (2D)
matrix = torch.tensor([[1, 2], [3, 4]])
print(matrix.shape)   # torch.Size([2, 2])

Creare tensori: metodi comuni

PyTorch fornisce molte funzioni factory per creare tensori con valori o forme specifici. torch.zeros e torch.ones riempiono i tensori con costanti; torch.rand estrae campioni da una distribuzione uniforme; torch.randn estrae campioni da una distribuzione normale standard. Sono gli elementi di base per inizializzare i pesi e generare dati sintetici.

import torch

zeros = torch.zeros(3, 4)        # 3x4 matrix of zeros
ones = torch.ones(2, 3)          # 2x3 matrix of ones
rand_uniform = torch.rand(3, 3)  # uniform in [0, 1)
rand_normal = torch.randn(3, 3)  # standard normal N(0,1)
arange = torch.arange(0, 10, 2) # [0, 2, 4, 6, 8]

print(zeros.dtype)    # torch.float32 (default)
print(arange)         # tensor([0, 2, 4, 6, 8])

Creare tensori da array NumPy

Spesso si parte da un array NumPy (proveniente da Pandas, scikit-learn e così via) e lo si deve convertire in un tensore PyTorch. torch.from_numpy condivide la memoria con l’array NumPy: modificando uno, si modifica anche l’altro. In alternativa, torch.tensor crea una copia. Sapere quale utilizzare evita bug imprevisti nelle pipeline di dati.

import torch
import numpy as np

arr = np.array([1.0, 2.0, 3.0])

# Shares memory with arr
t_shared = torch.from_numpy(arr)

# Makes an independent copy
t_copy = torch.tensor(arr)

arr[0] = 99.0
print(t_shared)   # tensor([99.,  2.,  3.])  <- changed
print(t_copy)     # tensor([1., 2., 3.])     <- unchanged

Tipi di dati dei tensori (dtypes)

I tensori hanno un dtype che controlla la precisione numerica e l’utilizzo della memoria. Il valore predefinito è torch.float32, lo standard per i pesi delle reti neurali. torch.float64 offre una precisione maggiore usando il doppio della memoria; torch.int64 viene utilizzato per le etichette intere. I dtype non corrispondenti causano errori a runtime, quindi li controlli sempre e li converta esplicitamente con .float() o .to(dtype).

import torch

f32 = torch.tensor([1.0, 2.0])         # float32 by default
f64 = torch.tensor([1.0, 2.0], dtype=torch.float64)
i64 = torch.tensor([1, 2, 3])          # int64 by default

print(f32.dtype)   # torch.float32
print(i64.dtype)   # torch.int64

# Cast to float32
labels = i64.float()
print(labels.dtype)   # torch.float32

Operazioni aritmetiche elemento per elemento

PyTorch sovraccarica gli operatori aritmetici standard di Python per eseguire operazioni elemento per elemento su tensori della stessa forma. Addizione, sottrazione, moltiplicazione e divisione funzionano tutte elemento per elemento. Queste operazioni sono altamente ottimizzate e vengono eseguite sulla GPU quando i tensori si trovano su un dispositivo CUDA. Le operazioni in-place, ad esempio add_, modificano direttamente il tensore senza allocare nuova memoria.

import torch

a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])

print(a + b)     # tensor([5., 7., 9.])
print(a * b)     # tensor([ 4., 10., 18.])
print(b / a)     # tensor([4., 2.5, 2.])
print(a ** 2)    # tensor([1., 4., 9.])

# In-place add
a.add_(1.0)
print(a)         # tensor([2., 3., 4.])

Moltiplicazione di matrici con torch.matmul

La moltiplicazione di matrici è l’operazione fondamentale all’interno di ogni livello di una rete neurale. torch.matmul (oppure l’operatore @) esegue la moltiplicazione di matrici e gestisce automaticamente i batch di matrici tramite broadcasting. Per gli input 2D calcola il prodotto matriciale standard; per input 3D o con più dimensioni esegue una moltiplicazione matriciale a batch. È così che un livello lineare calcola output = input @ weight.T + bias.

import torch

A = torch.randn(3, 4)   # 3x4
B = torch.randn(4, 5)   # 4x5
C = torch.matmul(A, B)  # 3x5
print(C.shape)           # torch.Size([3, 5])

# Equivalent using @ operator
C2 = A @ B
print(torch.allclose(C, C2))  # True

# Batched matmul
batch_A = torch.randn(8, 3, 4)  # batch of 8 matrices
batch_B = torch.randn(8, 4, 5)
result = batch_A @ batch_B       # torch.Size([8, 3, 5])

Modificare la forma dei tensori: view e reshape

Cambiare la forma di un tensore senza modificarne i dati è una delle operazioni più comuni nel deep learning. view richiede che il tensore sia contiguo in memoria e restituisce una vista (con dati condivisi); reshape funziona anche sui tensori non contigui, copiando i dati se necessario. Utilizzi -1 come dimensione jolly: PyTorch deduce la dimensione corretta. Appiattire una mappa delle feature 2D in un vettore 1D prima di un livello lineare è un caso d’uso tipico.

import torch

t = torch.arange(12).float()  # tensor of 12 elements
print(t.shape)                 # torch.Size([12])

m = t.view(3, 4)               # reshape to 3x4
print(m.shape)                 # torch.Size([3, 4])

m2 = t.view(2, -1)             # PyTorch infers 6 columns
print(m2.shape)                # torch.Size([2, 6])

# Flatten to 1D
flat = m.reshape(-1)
print(flat.shape)              # torch.Size([12])

Broadcasting: operare su forme diverse

Il broadcasting permette a PyTorch di eseguire operazioni su tensori con forme diverse, espandendo implicitamente le dimensioni. Le regole derivano da NumPy: le dimensioni vengono allineate a partire da destra e una dimensione di grandezza 1 può essere estesa per corrispondere all’altro tensore. Il broadcasting evita la ripetizione esplicita dei dati, risparmiando memoria. Viene utilizzato continuamente nei livelli delle reti neurali per aggiungere vettori di bias a matrici di output organizzate in batch.

import torch

# Matrix (3x4) + vector (4,)  -- vector broadcast over rows
matrix = torch.ones(3, 4)
bias = torch.tensor([1.0, 2.0, 3.0, 4.0])  # shape (4,)
result = matrix + bias
print(result.shape)   # torch.Size([3, 4])
print(result[0])      # tensor([2., 3., 4., 5.])

# Column vector (3,1) * row vector (1,4) -> (3,4)
col = torch.arange(1, 4).float().unsqueeze(1)  # (3,1)
row = torch.arange(1, 5).float().unsqueeze(0)  # (1,4)
print((col * row).shape)   # torch.Size([3, 4])

Controllare i dispositivi: CPU e CUDA

Ogni tensore risiede su un device: la cpu oppure una GPU CUDA come cuda:0. Controllare la disponibilità del dispositivo con torch.cuda.is_available() consente di scrivere codice indipendente dal dispositivo. Tutti i tensori coinvolti in un calcolo devono trovarsi sullo stesso dispositivo: tentare di sommare un tensore CPU e un tensore GPU genera un errore a runtime. Il modello standard consiste nel creare una variabile device e spostare tutto su di essa.

import torch

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print('Using device:', device)

# Create tensor directly on the chosen device
t = torch.randn(3, 3, device=device)
print(t.device)

# Move an existing CPU tensor to the device
cpu_tensor = torch.tensor([1.0, 2.0, 3.0])
gpu_tensor = cpu_tensor.to(device)
print(gpu_tensor.device)

Spostare i tensori sulla GPU con .to('cuda')

Addestrare reti neurali su una GPU può essere da 10 a 100 volte più veloce che su CPU per i modelli di grandi dimensioni. Dopo aver verificato la disponibilità di CUDA, sposti i tensori sulla GPU con .to('cuda') o .cuda(). Li riporti sulla CPU per convertirli in NumPy con .cpu() (NumPy non può accedere direttamente alla memoria della GPU). La chiamata .detach() rimuove un tensore dal grafo computazionale prima della conversione in NumPy.

import torch

# Simulate GPU workflow (falls back to CPU gracefully)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# Move model weights and data to GPU
weights = torch.randn(256, 128).to(device)
inputs = torch.randn(32, 128).to(device)  # batch of 32
outputs = inputs @ weights.T               # matmul on device
print(outputs.shape)   # torch.Size([32, 256])

# Convert back to NumPy for visualization
np_out = outputs.detach().cpu().numpy()
print(type(np_out))    # <class 'numpy.ndarray'>

Attributi e utilità utili dei tensori

Diversi attributi dei tensori e funzioni di utilità sono essenziali per il debugging e la gestione della forma dei dati. .shape restituisce le dimensioni; .numel() restituisce il numero totale di elementi; .dtype mostra il tipo di dati; .requires_grad indica se verranno tracciati i gradienti. Funzioni come torch.cat, torch.stack e torch.squeeze vengono utilizzate continuamente per assemblare i batch e rimuovere le dimensioni di grandezza 1.

import torch

t = torch.randn(4, 3, 2)
print(t.shape)          # torch.Size([4, 3, 2])
print(t.numel())        # 24
print(t.dtype)          # torch.float32

# Concatenate along dim 0
a = torch.ones(2, 3)
b = torch.zeros(3, 3)
cat = torch.cat([a, b], dim=0)   # shape (5, 3)
print(cat.shape)

# Remove size-1 dimensions
x = torch.randn(1, 5, 1)
print(x.squeeze().shape)         # torch.Size([5])

Verifica rapida

Verifichi la sua comprensione dei concetti di Machine Learning con Python presentati in questa lezione.

Riepilogo della lezione

In questa lezione ha imparato che: i tensori sono la struttura dati principale di PyTorch e supportano array n-dimensionali su CPU o GPU; le funzioni di creazione come torch.zeros, torch.randn e torch.from_numpy offrono metodi flessibili per inizializzare i dati; e spostare i tensori sulla GPU con .to(device) è il passaggio fondamentale per accelerare l’addestramento nel deep learning. Ora esploreremo la differenziazione automatica con Autograd.

Gratis per iniziare

Impara Python con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
30
Lezioni
120

Domande Frequenti

La lezione «Tensori PyTorch: creazione, operazioni e trasferimento alla GPU» è gratuita?

Sì — il testo completo di «Tensori PyTorch: creazione, operazioni e trasferimento alla GPU» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Machine Learning Academy, passa a CoddyKit PRO. Il corso Machine Learning Academy include 4 lezioni in totale.

Cosa imparerò in «Tensori PyTorch: creazione, operazioni e trasferimento alla GPU»?

Imparerete a creare tensori da liste Python e array NumPy, eseguire operazioni elemento per elemento e matriciali e trasferire i tensori sulla GPU con .to('cuda'). Eserciti Machine Learning Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Machine Learning Academy?

Non è richiesta alcuna esperienza precedente. Machine Learning Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Tensori PyTorch: creazione, operazioni e trasferimento alla GPU»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Machine Learning Academy?

Sì. Ogni lezione Machine Learning Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Tensori PyTorch: creazione, operazioni e trasferimento alla GPU
  2. Autograd: differenziazione automatica per la backpropagation
  3. Costruire una rete feedforward con nn.Module
  4. Ciclo di addestramento: loss, ottimizzatore ed epoche
← Torna a Machine Learning Academy