Apache MXNet - KVStore e visualizzazione

Questo capitolo tratta dei pacchetti python KVStore e della visualizzazione.

Pacchetto KVStore

KV stores sta per Key-Value store. È un componente critico utilizzato per l'addestramento multi-dispositivo. È importante perché la comunicazione dei parametri tra i dispositivi su una singola macchina e su più macchine viene trasmessa attraverso uno o più server con un KVStore per i parametri.

Cerchiamo di capire il funzionamento di KVStore con l'aiuto dei seguenti punti:

  • Ogni valore in KVStore è rappresentato da un file key e a value.

  • A ogni array di parametri nella rete viene assegnato un file key e il peso di tale matrice di parametri è riferito da value.

  • Dopodiché, il nodo di lavoro pushgradienti dopo l'elaborazione di un batch. Essi anchepull pesi aggiornati prima di elaborare un nuovo batch.

In parole semplici, possiamo dire che KVStore è un luogo per la condivisione dei dati in cui ogni dispositivo può inserire ed estrarre dati.

Inserimento ed estrazione dei dati

KVStore può essere pensato come un singolo oggetto condiviso tra diversi dispositivi come GPU e computer, in cui ogni dispositivo è in grado di inserire ed estrarre dati.

Di seguito sono riportati i passaggi di implementazione che devono essere seguiti dai dispositivi per inserire ed estrarre i dati:

Fasi di implementazione

Initialisation- Il primo passo è inizializzare i valori. Qui per il nostro esempio, inizializzeremo una coppia (int, NDArray) in KVStrore e successivamente estraeremo i valori -

import mxnet as mx
kv = mx.kv.create('local') # create a local KVStore.
shape = (3,3)
kv.init(3, mx.nd.ones(shape)*2)
a = mx.nd.zeros(shape)
kv.pull(3, out = a)
print(a.asnumpy())

Output

Questo produce il seguente output:

[[2. 2. 2.]
[2. 2. 2.]
[2. 2. 2.]]

Push, Aggregate, and Update - Una volta inizializzato, possiamo inserire un nuovo valore in KVStore con la stessa forma alla chiave -

kv.push(3, mx.nd.ones(shape)*8)
kv.pull(3, out = a)
print(a.asnumpy())

Output

L'output è fornito di seguito:

[[8. 8. 8.]
 [8. 8. 8.]
 [8. 8. 8.]]

I dati utilizzati per il push possono essere archiviati su qualsiasi dispositivo come GPU o computer. Possiamo anche inserire più valori nella stessa chiave. In questo caso, KVStore prima sommerà tutti questi valori e poi invierà il valore aggregato come segue:

contexts = [mx.cpu(i) for i in range(4)]
b = [mx.nd.ones(shape, ctx) for ctx in contexts]
kv.push(3, b)
kv.pull(3, out = a)
print(a.asnumpy())

Output

Vedrai il seguente output:

[[4. 4. 4.]
 [4. 4. 4.]
 [4. 4. 4.]]

Per ogni push applicato, KVStore combinerà il valore inviato con il valore già memorizzato. Sarà fatto con l'aiuto di un programma di aggiornamento. Qui, il programma di aggiornamento predefinito è ASSIGN.

def update(key, input, stored):
   print("update on key: %d" % key)
   
   stored += input * 2
kv.set_updater(update)
kv.pull(3, out=a)
print(a.asnumpy())

Output

Quando esegui il codice sopra, dovresti vedere il seguente output:

[[4. 4. 4.]
 [4. 4. 4.]
 [4. 4. 4.]]

Example

kv.push(3, mx.nd.ones(shape))
kv.pull(3, out=a)
print(a.asnumpy())

Output

Di seguito è riportato l'output del codice:

update on key: 3
[[6. 6. 6.]
 [6. 6. 6.]
 [6. 6. 6.]]

Pull - Come per Push, possiamo anche trasferire il valore su più dispositivi con una singola chiamata come segue:

b = [mx.nd.ones(shape, ctx) for ctx in contexts]
kv.pull(3, out = b)
print(b[1].asnumpy())

Output

L'output è indicato di seguito:

[[6. 6. 6.]
 [6. 6. 6.]
 [6. 6. 6.]]

Esempio di implementazione completo

Di seguito è riportato l'esempio di implementazione completo:

import mxnet as mx
kv = mx.kv.create('local')
shape = (3,3)
kv.init(3, mx.nd.ones(shape)*2)
a = mx.nd.zeros(shape)
kv.pull(3, out = a)
print(a.asnumpy())
kv.push(3, mx.nd.ones(shape)*8)
kv.pull(3, out = a) # pull out the value
print(a.asnumpy())
contexts = [mx.cpu(i) for i in range(4)]
b = [mx.nd.ones(shape, ctx) for ctx in contexts]
kv.push(3, b)
kv.pull(3, out = a)
print(a.asnumpy())
def update(key, input, stored):
   print("update on key: %d" % key)
   stored += input * 2
kv._set_updater(update)
kv.pull(3, out=a)
print(a.asnumpy())
kv.push(3, mx.nd.ones(shape))
kv.pull(3, out=a)
print(a.asnumpy())
b = [mx.nd.ones(shape, ctx) for ctx in contexts]
kv.pull(3, out = b)
print(b[1].asnumpy())

Gestione delle coppie chiave-valore

Tutte le operazioni che abbiamo implementato sopra coinvolgono una singola chiave, ma KVStore fornisce anche un'interfaccia per a list of key-value pairs -

Per un unico dispositivo

Di seguito è riportato un esempio per mostrare un'interfaccia KVStore per un elenco di coppie chiave-valore per un singolo dispositivo:

keys = [5, 7, 9]
kv.init(keys, [mx.nd.ones(shape)]*len(keys))
kv.push(keys, [mx.nd.ones(shape)]*len(keys))
b = [mx.nd.zeros(shape)]*len(keys)
kv.pull(keys, out = b)
print(b[1].asnumpy())

Output

Riceverai il seguente output:

update on key: 5
update on key: 7
update on key: 9
[[3. 3. 3.]
 [3. 3. 3.]
 [3. 3. 3.]]

Per più dispositivi

Di seguito è riportato un esempio per mostrare un'interfaccia KVStore per un elenco di coppie chiave-valore per più dispositivi:

b = [[mx.nd.ones(shape, ctx) for ctx in contexts]] * len(keys)
kv.push(keys, b)
kv.pull(keys, out = b)
print(b[1][1].asnumpy())

Output

Vedrai il seguente output:

update on key: 5
update on key: 7
update on key: 9
[[11. 11. 11.]
 [11. 11. 11.]
 [11. 11. 11.]]

Pacchetto di visualizzazione

Il pacchetto di visualizzazione è il pacchetto Apache MXNet utilizzato per rappresentare la rete neurale (NN) come un grafico di calcolo costituito da nodi e bordi.

Visualizza la rete neurale

Nell'esempio seguente useremo mx.viz.plot_networkper visualizzare la rete neurale. I seguenti sono i prerequisiti per questo:

Prerequisites

  • Taccuino Jupyter

  • Libreria Graphviz

Esempio di implementazione

Nell'esempio seguente visualizzeremo un campione NN per la fattorizzazione a matrice lineare -

import mxnet as mx
user = mx.symbol.Variable('user')
item = mx.symbol.Variable('item')
score = mx.symbol.Variable('score')

# Set the dummy dimensions
k = 64
max_user = 100
max_item = 50

# The user feature lookup
user = mx.symbol.Embedding(data = user, input_dim = max_user, output_dim = k)

# The item feature lookup
item = mx.symbol.Embedding(data = item, input_dim = max_item, output_dim = k)

# predict by the inner product and then do sum
N_net = user * item
N_net = mx.symbol.sum_axis(data = N_net, axis = 1)
N_net = mx.symbol.Flatten(data = N_net)

# Defining the loss layer
N_net = mx.symbol.LinearRegressionOutput(data = N_net, label = score)

# Visualize the network
mx.viz.plot_network(N_net)