Apache MXNet - KVStore i wizualizacja
W tym rozdziale omówiono pakiety KVStore w języku Python oraz wizualizację.
Pakiet KVStore
Sklepy KV to skrót od Key-Value store. Jest to krytyczny komponent używany do treningu na wielu urządzeniach. Jest to ważne, ponieważ komunikacja parametrów między urządzeniami na jednym, a także na wielu maszynach jest przesyłana przez jeden lub więcej serwerów z KVStore dla parametrów.
Pozwól nam zrozumieć działanie KVStore za pomocą następujących punktów:
Każda wartość w KVStore jest reprezentowana przez key i a value.
Każda tablica parametrów w sieci ma przypisany plik key a wagi tej tablicy parametrów są określane przez value.
Następnie węzły robocze pushgradienty po przetworzeniu partii. Oni teżpull zaktualizowane wagi przed przetworzeniem nowej partii.
Krótko mówiąc, możemy powiedzieć, że KVStore to miejsce do udostępniania danych, w którym każde urządzenie może przesyłać i pobierać dane.
Dane push-in i pull-out
KVStore można traktować jako pojedynczy obiekt współużytkowany przez różne urządzenia, takie jak GPU i komputery, w których każde urządzenie może wprowadzać i pobierać dane.
Poniżej przedstawiono kroki implementacji, które muszą wykonać urządzenia, aby wypychać i pobierać dane:
Etapy wdrażania
Initialisation- Pierwszym krokiem jest zainicjowanie wartości. Tutaj, dla naszego przykładu, zainicjujemy parę (int, NDArray) w KVStrore, a następnie wyciągniemy wartości -
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
Daje to następujący wynik -
[[2. 2. 2.]
[2. 2. 2.]
[2. 2. 2.]]
Push, Aggregate, and Update - Po zainicjowaniu możemy przesłać nową wartość do KVStore o tym samym kształcie do klucza -
kv.push(3, mx.nd.ones(shape)*8)
kv.pull(3, out = a)
print(a.asnumpy())
Output
Dane wyjściowe podano poniżej -
[[8. 8. 8.]
[8. 8. 8.]
[8. 8. 8.]]
Dane używane do wypychania mogą być przechowywane na dowolnym urządzeniu, takim jak GPU lub komputery. Możemy również wprowadzić wiele wartości do tego samego klucza. W takim przypadku KVStore najpierw zsumuje wszystkie te wartości, a następnie przekaże zagregowaną wartość w następujący sposób -
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
Zobaczysz następujący wynik -
[[4. 4. 4.]
[4. 4. 4.]
[4. 4. 4.]]
Dla każdego zastosowanego wypchnięcia KVStore połączy przekazaną wartość z wartością już zapisaną. Zostanie to zrobione za pomocą aktualizatora. Tutaj domyślnym aktualizatorem jest 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
Po wykonaniu powyższego kodu powinieneś zobaczyć następujące dane wyjściowe -
[[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
Poniżej podano wynik kodu -
update on key: 3
[[6. 6. 6.]
[6. 6. 6.]
[6. 6. 6.]]
Pull - Podobnie jak w przypadku Push, możemy również przeciągnąć wartość na kilka urządzeń za pomocą jednego wywołania w następujący sposób -
b = [mx.nd.ones(shape, ctx) for ctx in contexts]
kv.pull(3, out = b)
print(b[1].asnumpy())
Output
Dane wyjściowe podano poniżej -
[[6. 6. 6.]
[6. 6. 6.]
[6. 6. 6.]]
Pełny przykład implementacji
Poniżej podano pełny przykład wdrożenia -
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())
Obsługa par klucz-wartość
Wszystkie operacje, które zaimplementowaliśmy powyżej, dotyczą jednego klucza, ale KVStore zapewnia również interfejs dla a list of key-value pairs -
Dla jednego urządzenia
Poniżej znajduje się przykład pokazujący interfejs KVStore dla listy par klucz-wartość dla jednego urządzenia -
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
Otrzymasz następujący wynik -
update on key: 5
update on key: 7
update on key: 9
[[3. 3. 3.]
[3. 3. 3.]
[3. 3. 3.]]
Dla wielu urządzeń
Poniżej znajduje się przykład pokazujący interfejs KVStore dla listy par klucz-wartość dla wielu urządzeń -
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
Zobaczysz następujący wynik -
update on key: 5
update on key: 7
update on key: 9
[[11. 11. 11.]
[11. 11. 11.]
[11. 11. 11.]]
Pakiet wizualizacji
Pakiet wizualizacji to pakiet Apache MXNet używany do reprezentowania sieci neuronowej (NN) jako grafu obliczeniowego składającego się z węzłów i krawędzi.
Wizualizuj sieć neuronową
W poniższym przykładzie użyjemy mx.viz.plot_networkwizualizacja sieci neuronowej. Następujące warunki są do tego niezbędne -
Prerequisites
Notatnik Jupyter
Biblioteka Graphviz
Przykład implementacji
W poniższym przykładzie zwizualizujemy próbkę NN dla liniowej faktoryzacji macierzy -
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)