Modelli e strati

Nell'apprendimento automatico, un modello è una funzione con apprendibili parametri che mappa un ingresso ad un'uscita. 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 Livelli dove si costruisce un modello utilizzando i livelli.
  2. utilizzando l'API Core ops di livello inferiore come tf.matMul() , tf.add() , etc.

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

Creazione di modelli con l'API dei livelli

Ci sono due modi per creare un modello usando gli strati API: Un modello sequenziale, e un modello funzionale. Le prossime due sezioni esaminano ciascun tipo più da vicino.

Il modello sequenziale

Il più comune tipo di modello è il Sequential modello, che è una pila di strati lineare. È possibile creare un Sequential modello passando un elenco dei livelli al sequential() la funzione:

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

O tramite l' add() Metodo:

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 strato del modello ha bisogno di un inputShape . Assicurati di escludere le dimensioni dei lotti nel fornire inputShape . Ad esempio, se si prevede di alimentare i tensori modello di forma [B, 784] , dove B può essere di qualsiasi dimensione del lotto, 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 il tf.model() funzione. La differenza fondamentale tra tf.model() e tf.sequential() è che tf.model() consente di creare un grafico arbitrario di strati, purché essi non hanno cicli.

C'è un frammento di codice che definisce lo stesso modello come sopra utilizzando il tf.model() API:

// 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 strato per collegarlo all'uscita di un altro livello. Il risultato di apply() in questo caso è uno SymbolicTensor , che agisce come un Tensor ma senza valori concreti.

Si noti che a differenza del modello sequenziale, creiamo uno SymbolicTensor via tf.input() invece di fornire un inputShape al primo strato.

apply() può anche dare un concreto Tensor , se si passa un concreto Tensor ad esso:

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, è possibile accedere ai livelli del modello tramite model.layers , e più specificamente model.inputLayers e model.outputLayers .

Convalida

Sia il modello sequenziale e il modello funzionale sono istanze della LayersModel di classe. Uno dei principali vantaggi di lavorare con un LayersModel è di convalida: ti costringe a specificare la forma di ingresso e lo userà in seguito per convalidare il vostro input. Il LayersModel fa anche inferire automaticamente forma come i flussi di dati attraverso gli strati. 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

Chiamare model.summary() per stampare una sintesi utile del modello, che comprende:

  • 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 #
dense_Dense1 (denso) [nullo,32] 25120
dense_Dense2 (Densi) [nullo,10] 330
Parametri totali: 25450
Parametri addestrabili: 25450
Parametri non addestrabili: 0

Notare i null valori nelle forme uscita degli strati: un promemoria che il modello prevede l'ingresso di avere una dimensione del lotto come dimensione esterna, che in questo caso può essere flessibile a causa della null valore.

Serializzazione

Uno dei principali vantaggi di utilizzare una LayersModel sopra l'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 del training (perdita, ottimizzatore, metriche).
  • lo stato dell'ottimizzatore, consentendo di riprendere l'allenamento.

Per salvare o caricare un modello è sufficiente 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. Vedere la model.save() documentation e il salvataggio e il carico guida per il modo di salvare diversi supporti (ad esempio archiviazione di file, IndexedDB , innescare un 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 layer 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 provarlo, si può chiamare il apply() metodo con un tensore concreto:

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

IMPORTANTE: se si aggiunge un livello personalizzato, si perde la possibilità di serializzare un modello.

Creazione di modelli con l'API Core

All'inizio di questa guida, abbiamo detto che esistono due modi per creare un modello di machine learning in TensorFlow.js.

La regola generale è cercare sempre di utilizzare l'API Livelli primo, poiché è modellato API Keras ben definita, 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, la formazione sul monitoraggio, la portabilità e il controllo della sicurezza.

Potresti voler utilizzare l'API Core ogni volta che:

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

Modelli in Core API sono solo funzioni che richiedono uno o più Tensors e restituiscono un Tensor . Lo stesso modello sopra scritto utilizzando l'API Core si presenta così:

// 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 è sostenuta da una Variable che segnala al TensorFlow.js che questi tensori sono apprendibile. È possibile creare una Variable utilizzando tf.variable () e passando in un esistente Tensor .

In questa guida hai familiarizzato con i diversi modi per creare un modello utilizzando i livelli e l'API principale. Avanti, vedere il modelli di formazione guida per come addestrare un modello.