1. Ritrovare ciò che il kernel sa ancora
Il file del notebook e lo stato del kernel non raccontano sempre la stessa storia. Una variabile può venire da una cella eliminata, una lista può essere stata modificata più volte, e un oggetto caricato prima dell'ultima modifica al codice può restare in memoria. I risultati mostrati non dimostrano quindi che le celle attuali producano ancora quei risultati nel loro ordine visibile.
Conserva una copia di lavoro, riavvia il kernel, poi esegui le celle dall'inizio alla fine. Annota la prima cella che fallisce o cambia risultato. Cerca la dipendenza mancante invece di reiniettare manualmente una variabile da una vecchia sessione. Il kernel Jupyter è un processo separato; chiudere una scheda non equivale a ricostruire un ambiente pulito.
Fai anche l'inventario degli effetti esterni: download, installazione di pacchetti, cambio di directory, lettura di un file già prodotto e uso di una variabile d'ambiente. Una cella il cui risultato sembra immediato può semplicemente riutilizzare un file vecchio. Il tuo futuro script deve poter distinguere un input volontario da un residuo di prova.
2. Scrivere il contratto prima di spostare il codice
Scegli un'unica attività da estrarre. Per esempio: leggere un file di punteggi, mantenere gli identificatori il cui punteggio raggiunge una soglia e scrivere il risultato. L'esempio di questa guida è didattico, non eseguito e senza GPU. Serve a mostrare le dipendenze di un'esecuzione, non ad annunciare una misura o uno strumento fornito con Kernodeck.
Definisci input, parametro e output con sufficiente precisione per verificare la trasformazione. Qui la soglia è inclusiva: un punteggio pari a 0,5 viene mantenuto. Gli identificatori devono restare associati ai loro punteggi e l'ordine di input è preservato. Un output esistente non deve essere sostituito involontariamente da una nuova prova.
Questo passaggio evita una migrazione ambigua: se il notebook eliminava i punteggi pari alla soglia mentre lo script li mantiene, hai cambiato il calcolo. Decidi esplicitamente se è una correzione o una regressione. Mantieni un caso esattamente al limite, non solo due valori distanti.
Scorri la tabella per leggere tutte le colonne.| Elemento | Valore dell'esempio | Criterio |
|---|---|---|
| Input | a : 0,4 ; b : 0,8 ; c : 0,5 | Tre identificatori distinti, punteggi già validati tra 0 e 1. |
| Parametro | Soglia 0,5 | Confronto maggiore o uguale. |
| Output atteso | b, poi c | Due identificatori, senza duplicazione né riordinamento. |
3. Estrarre una funzione che non dipende più da una cella
Separa la trasformazione dalle operazioni di lettura e scrittura. Una funzione di calcolo riceve i suoi dati e la sua soglia, poi restituisce gli identificatori selezionati. Non consulta una variabile globale chiamata soglia, non apre implicitamente un file e non modifica la lista di input. Questo permette al notebook e allo script di chiamare esattamente lo stesso calcolo.
Nell'estratto, i dati si presumono già validati secondo il contratto precedente. La funzione non costituisce quindi un validatore completo di file. Questo limite è voluto: verifica i formati all'ingresso del programma, poi mantieni la trasformazione facile da comprendere. Aggiungere un parametro non deve richiedere di ritrovare la cella che aveva cambiato un valore.
Il notebook può restare il tuo strumento di esplorazione. Fagli importare questa funzione invece di mantenere una seconda copia. Dopo aver modificato il modulo, riparti da un kernel nuovo per confrontare i due percorsi; una vecchia funzione già importata non deve falsare la verifica.
def retenir_identifiants(records, seuil):
return [
record["id"]
for record in records
if record["score"] >= seuil
]
if __name__ == "__main__":
records = [
{"id": "a", "score": 0.4},
{"id": "b", "score": 0.8},
{"id": "c", "score": 0.5},
]
attendu = ["b", "c"]
obtenu = retenir_identifiants(records, 0.5)
if obtenu != attendu:
raise SystemExit("Sélection inattendue")4. Rendere i parametri un input visibile
Il punto di ingresso dello script elabora gli argomenti, valida le scelte e chiama le funzioni. Il modulo standard argparse descrive le opzioni e produce un aiuto; non conosce le tue regole di business. Un float accettato sintatticamente può ancora essere fuori dall'intervallo consentito. La soglia di questo esempio richiede quindi un controllo aggiuntivo.
Specifica la risoluzione dei percorsi: relativi alla directory da cui viene lanciato il comando, o a una cartella di progetto scelta esplicitamente. Non usare un cambio di directory nascosto nel mezzo del calcolo. Il blocco qui sotto mostra solo l'analisi degli argomenti; la lettura dei dati e la scrittura restano da collegare nel programma del lettore.
Tieni i segreti fuori da questi argomenti. I parametri condivisibili descrivono l'esperimento; gli accessi a un repository o a uno storage seguono un altro canale. Un comando utile a un collega deve poter essere copiato senza copiare anche un token.
import argparse
from pathlib import Path
def leggi_argomenti():
parser = argparse.ArgumentParser()
parser.add_argument("--input", required=True, type=Path)
parser.add_argument("--output", required=True, type=Path)
parser.add_argument("--seuil", required=True, type=float)
args = parser.parse_args()
if not 0 <= args.seuil <= 1:
parser.error("Le seuil doit être compris entre 0 et 1.")
return args5. Dare allo script una fine e output verificabili
Metti l'orchestrazione in una funzione main e attivala sotto la condizione if __name__ == "__main__". Il modulo può così essere importato dal notebook senza avviare immediatamente l'elaborazione. Gli import definiscono gli strumenti; l'entry point principale decide quando leggere, calcolare e scrivere.
Assegna una cartella distinta a ogni esecuzione. Salva i parametri non sensibili realmente usati e l'identità dell'input, poi scrivi i risultati. Per la nostra selezione, verifica il numero di identificatori, la loro appartenenza all'input e la regola della soglia. Un file JSON ben formato può contenere gli identificatori sbagliati; la sua sola presenza non basta.
Prevedi un fallimento esplicito se il file di input manca o se la destinazione non è utilizzabile. Evita di sostituire questi problemi con una lista vuota: potrebbe essere interpretata come una selezione valida. Il programma deve distinguere nessun risultato che soddisfi la soglia e nessun risultato perché la lettura è fallita.
6. Confrontare in due esecuzioni nuove
Usa prima le tre righe didattiche. Con la soglia 0,5, aspettati b e c; con 0,9, aspettati una lista vuota; con 0,4, aspettati i tre identificatori. Queste risposte si deducono dal contratto e non sono presentate qui come risultati eseguiti. Permettono di individuare un operatore di confronto invertito o un ordine sbagliato.
Esegui poi il tuo notebook riavviato e il tuo script in un processo nuovo, sullo stesso input. Confronta i valori utili, non gli screenshot né gli orari scritti nei file. Aggiungi un secondo set rappresentativo e un input non valido. Documenta le differenze attese, come una presentazione più sobria degli output.
Una conversione nbconvert può accelerare lo spostamento iniziale delle celle, ma le sue magic command possono ancora dipendere da Jupyter. Rimuovi o sostituisci le istruzioni proprie del notebook, le visualizzazioni inutili e le installazioni improvvisate. L'export è un punto di partenza; il confronto da uno stato nuovo decide se la migrazione è conclusa.
7. Passare alla GPU senza reintrodurre lo stato nascosto
Una volta compreso il percorso CPU, collega il caricamento del modello e il backend alla stessa struttura esplicita. Conserva versioni, precisione, input e destinazione. Il passaggio alla GPU non corregge né un ordine di celle incoerente né un file prodotto da un vecchio tentativo. Verifica separatamente che PyTorch possa davvero calcolare sul dispositivo scelto.
Se due lanci producono valori diversi, distingui uno stato dimenticato, una sorgente casuale e i limiti numerici del calcolo. Un seed non è una promessa universale di identità tra versioni e hardware. Per l'addestramento interrotto, usa la procedura dedicata ai checkpoint: questa guida trasforma l'entry point, senza ricostituire gli stati di ottimizzatore o dei generatori.
L'output utile è un programma che puoi descrivere in un comando, con i suoi prerequisiti e un controllo del risultato. Il notebook resta libero di esplorare e tracciare; non porta più da solo la memoria di come il calcolo debba essere avviato.