Modelli e strati

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

Nell'apprendimento automatico, un modello è una funzione con parametri apprendibili che associa un input a un output. I parametri ottimali si ottengono addestrando il modello sui dati. Un modello ben addestrato fornirà una mappatura accurata dall'input all'output desiderato.

In TensorFlow.js ci sono due modi per creare un modello di machine learning:

  1. utilizzando l'API Layers in cui si crea un modello utilizzando i layer .
  2. utilizzando l'API Core con operazioni di livello inferiore come tf.matMul() , tf.add() , ecc.

Per prima cosa, esamineremo l'API Layers, che è un'API di livello superiore per la creazione di modelli. Quindi, mostreremo come costruire lo stesso modello usando l'API Core.

Creazione di modelli con l'API Layers

Esistono due modi per creare un modello utilizzando l'API Layers: un modello sequenziale e un modello funzionale . Le prossime due sezioni esaminano ogni tipo più da vicino.

Il modello sequenziale

Il tipo più comune di modello è il modello Sequential , che è una pila lineare di livelli. Puoi creare un modello Sequential passando un elenco di livelli alla funzione sequential() :

const model = tf.sequential({
 layers: [
   tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}),
   tf.layers.dense({units: 10, activation: 'softmax'}),
 ]
});

O tramite il metodo add() :

const model = tf.sequential();
model.add(tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}));
model.add(tf.layers.dense({units: 10, activation: 'softmax'}));

IMPORTANTE: il primo livello nel modello necessita di un inputShape . Assicurati di escludere la dimensione del batch quando fornisci inputShape . Ad esempio, se si intende alimentare i tensori del modello di shape [B, 784] , dove B può essere qualsiasi dimensione batch, specificare inputShape come [784] durante la creazione del modello.

È possibile accedere ai livelli del modello tramite model.layers e, più specificamente, model.inputLayers e model.outputLayers .

Il modello funzionale

Un altro modo per creare un LayersModel è tramite la funzione tf.model() . La differenza fondamentale tra tf.model() e tf.sequential() è che tf.model() consente di creare un grafico arbitrario di livelli, purché non abbiano cicli.

Ecco un frammento di codice che definisce lo stesso modello di cui sopra utilizzando l'API tf.model() :

// Create an arbitrary graph of layers, by connecting them
// via the apply() method.
const input = tf.input({shape: [784]});
const dense1 = tf.layers.dense({units: 32, activation: 'relu'}).apply(input);
const dense2 = tf.layers.dense({units: 10, activation: 'softmax'}).apply(dense1);
const model = tf.model({inputs: input, outputs: dense2});

Chiamiamo apply() su ogni livello per connetterlo all'output di un altro livello. Il risultato di apply() in questo caso è un SymbolicTensor , che agisce come un Tensor ma senza valori concreti.

Nota che a differenza del modello sequenziale, creiamo un SymbolicTensor tramite tf.input() invece di fornire un inputShape al primo livello.

apply() può anche darti un Tensor concreto, se gli passi un Tensor concreto:

const t = tf.tensor([-2, 1, 0, 5]);
const o = tf.layers.activation({activation: 'relu'}).apply(t);
o.print(); // [0, 1, 0, 5]

Questo può essere utile quando si testano i livelli in isolamento e si vede il loro output.

Proprio come in un modello sequenziale, puoi accedere ai livelli del modello tramite model.layers e più specificamente model.inputLayers e model.outputLayers .

Convalida

Sia il modello sequenziale che il modello funzionale sono istanze della classe LayersModel . Uno dei principali vantaggi di lavorare con un LayersModel è la convalida: ti obbliga a specificare la forma dell'input e la utilizzerà in seguito per convalidare l'input. LayersModel esegue anche l'inferenza della forma automatica mentre i dati fluiscono attraverso i livelli. Conoscere la forma in anticipo consente al modello di creare automaticamente i suoi parametri e può dirti se due livelli consecutivi non sono compatibili tra loro.

Riepilogo del modello

Chiama model.summary() per stampare un utile riepilogo del modello, che include:

  • Nome e tipo di tutti i livelli nel modello.
  • Forma di output per ogni livello.
  • Numero di parametri di peso di ogni strato.
  • Se il modello ha una topologia generale (discussa di seguito), gli input ricevuti da ogni livello
  • Il numero totale di parametri addestrabili e non addestrabili del modello.

Per il modello che abbiamo definito sopra, otteniamo il seguente output sulla console:

Livello (tipo) Forma di uscita Param #
denso_denso1 (denso) [nullo,32] 25120
denso_denso2 (denso) [nullo,10] 330
Totale parametri: 25450
Parametri addestrabili: 25450
Parametri non addestrabili: 0

Nota i valori null nelle forme di output dei livelli: un promemoria per ricordare che il modello prevede che l'input abbia una dimensione batch come dimensione più esterna, che in questo caso può essere flessibile a causa del valore null .

Serializzazione

Uno dei principali vantaggi dell'utilizzo di LayersModel rispetto all'API di livello inferiore è la possibilità di salvare e caricare un modello. Un LayersModel conosce:

  • l'architettura del modello, consentendo di ricreare il modello.
  • i pesi del modello
  • la configurazione dell'allenamento (perdita, ottimizzatore, metriche).
  • lo stato dell'ottimizzatore, consentendo di riprendere l'allenamento.

Per salvare o caricare un modello basta 1 riga di codice:

const saveResult = await model.save('localstorage://my-model-1');
const model = await tf.loadLayersModel('localstorage://my-model-1');

L'esempio sopra salva il modello nella memoria locale nel browser. Consulta la model.save() documentation e la guida al salvataggio e al caricamento per sapere come salvare su diversi supporti (ad es. archiviazione file, IndexedDB , attivare il download del browser, ecc.)

Livelli personalizzati

I livelli sono gli elementi costitutivi di un modello. Se il tuo modello sta eseguendo un calcolo personalizzato, puoi definire un livello personalizzato, che interagisce bene con il resto dei livelli. Di seguito definiamo un livello personalizzato che calcola la somma dei quadrati:

class SquaredSumLayer extends tf.layers.Layer {
 constructor() {
   super({});
 }
 // In this case, the output is a scalar.
 computeOutputShape(inputShape) { return []; }

 // call() is where we do the computation.
 call(input, kwargs) { return input.square().sum();}

 // Every layer needs a unique name.
 getClassName() { return 'SquaredSum'; }
}

Per testarlo, possiamo chiamare il metodo apply() con un tensore concreto:

const t = tf.tensor([-2, 1, 0, 5]);
const o = new SquaredSumLayer().apply(t);
o.print(); // prints 30

IMPORTANTE: se aggiungi un livello personalizzato, perdi la possibilità di serializzare un modello.

Creazione di modelli con l'API Core

All'inizio di questa guida, abbiamo menzionato che esistono due modi per creare un modello di apprendimento automatico in TensorFlow.js.

La regola generale è provare sempre a utilizzare prima l'API Layers, poiché è modellata sull'API Keras ben adottata che segue le migliori pratiche e riduce il carico cognitivo . L'API Layers offre anche varie soluzioni pronte all'uso come l'inizializzazione del peso, la serializzazione del modello, il monitoraggio della formazione, la portabilità e il controllo della sicurezza.

Potresti voler utilizzare l'API principale ogni volta che:

  • Hai bisogno della massima flessibilità o controllo.
  • Non è necessaria la serializzazione o è possibile implementare la propria logica di serializzazione.

I modelli nell'API Core sono solo funzioni che accettano uno o più Tensors e restituiscono un Tensor . Lo stesso modello scritto sopra utilizzando l'API Core è simile al seguente:

// The weights and biases for the two dense layers.
const w1 = tf.variable(tf.randomNormal([784, 32]));
const b1 = tf.variable(tf.randomNormal([32]));
const w2 = tf.variable(tf.randomNormal([32, 10]));
const b2 = tf.variable(tf.randomNormal([10]));

function model(x) {
  return x.matMul(w1).add(b1).relu().matMul(w2).add(b2).softmax();
}

Si noti che nell'API Core siamo responsabili della creazione e dell'inizializzazione dei pesi del modello. Ogni peso è supportato da una Variable che segnala a TensorFlow.js che questi tensori sono apprendibili. Puoi creare una Variable usando tf.variable() e passando un Tensor esistente.

In questa guida hai familiarizzato con i diversi modi per creare un modello utilizzando i livelli e l'API principale. Quindi, vedere la guida ai modelli di addestramento per come addestrare un modello.