Глава 3: Создание сети глубокого обучения с использованием MXNet

Мы начнем наше углубленное исследование фреймворков глубокого обучения с одного из самых многообещающих: Apache MXNet. Мы рассмотрим его основные компоненты, включая интерфейс Gluon, NDArrays и пакет MXNet в Python. Вы узнаете, как можно сохранять свою работу, например, сети, обученные на файлах данных, и другие полезные вещи, о которых следует помнить, работая с MXNet.

MXNet поддерживает различные языки программирования через свой API, большинство из которых полезны для науки о данных. Языки, такие как Python, Julia, Scala, R, Perl и C++, имеют свои обертки системы MXNet, что делает их легко интегрируемыми в ваш конвейер данных.

Кроме того, MXNet позволяет распараллеливать вычисления, что позволяет в полной мере использовать дополнительные аппаратные ресурсы вашей машины, такие как дополнительные процессоры (CPU) и графические процессоры (GPU). Это делает MXNet довольно быстрым, что важно при решении вычислительно сложных задач, подобных тем, которые встречаются в большинстве приложений глубокого обучения.

Интересно, что системы глубокого обучения, созданные в MXNet, могут быть развернуты на всех видах компьютерных платформ, включая умные устройства. Это возможно благодаря процессу, называемому амальгамацией, который переносит всю систему в один файл, который затем может быть выполнен как автономная программа. Амальгамация в MXNet была создана Джеком Денгом и включает разработку файлов .cc, единственной зависимостью которых является библиотека BLAS. Файлы такого типа, как правило, довольно большие (более 30000 строк). Также есть возможность компиляции файлов .h с использованием программы emscripten. Эта программа не зависит от какой-либо библиотеки и может использоваться другими языками программирования с соответствующим API.

Наконец, существует несколько руководств по MXNet, если вы хотите узнать больше о его различных функциях. Поскольку MXNet является проектом с открытым исходным кодом, вы даже можете создать свое собственное руководство, если захотите.

Более того, это кроссплатформенный инструмент, работающий на всех основных операционных системах. MXNet существует достаточно долго, чтобы стать темой многих исследований, включая известную научную статью Чена и др.7

Основные компоненты

Интерфейс Gluon

Gluon - это простой интерфейс для всей вашей работы с глубоким обучением с использованием MXNet. Вы устанавливаете его на свою машину точно так же, как любую библиотеку Python:

pip install mxnet --pre --user

Главное преимущество Gluon в том, что он прост. Он предлагает абстракцию всего процесса построения сети, что может быть пугающим для новичков в этой области. Кроме того, Gluon очень быстрый, не добавляя значительных накладных расходов при обучении вашей системы глубокого обучения. Более того, Gluon может обрабатывать динамические графы, предлагая некоторую гибкость в структуре создаваемых ANN. Наконец, Gluon имеет общую гибкую структуру, что делает процесс разработки для любой ANN менее жестким.

Естественно, для работы Gluon у вас должен быть установлен MXNet на вашей машине (хотя это не требуется, если вы используете контейнер Docker, поставляемый с этой книгой). Это достигается с помощью знакомой команды pip:

pip install mxnet --pre --user

Из-за его полезности и отличной интеграции с MXNet, мы будем использовать Gluon на протяжении всей этой главы, исследуя этот фреймворк глубокого обучения. Однако, чтобы лучше понять MXNet, мы сначала кратко рассмотрим, как вы можете использовать некоторые из его других функций (которые пригодятся для одного из примеров, которые мы рассмотрим позже).

NDArrays

NDArray — это особенно полезная структура данных, которая используется в проектах MXNet. NDArray по сути представляют собой массивы NumPy, но с добавленной возможностью асинхронной обработки на ЦП. Они также совместимы с распределенными облачными архитектурами и могут использовать автоматическое дифференцирование, что особенно полезно при обучении системы глубокого обучения, но NDArrays также можно эффективно использовать и в других приложениях машинного обучения. NDArrays являются частью пакета MXNet, который мы скоро рассмотрим. Вы можете импортировать модуль NDArrays следующим образом:

from mxnet import nd

Например, чтобы создать новый NDArray, состоящий из 4 строк и 5 столбцов, вы можете набрать следующее:

nd.empty((4, 5))

Результат будет отличаться каждый раз, когда вы его запускаете, поскольку фреймворк будет выделять любое значение, которое он найдет в тех частях памяти, которые он выделяет для этого массива. Если вы хотите, чтобы NDArray содержал только нули, введите:

nd.zeros((4, 5))

Чтобы узнать количество строк и столбцов переменной, которой присвоен NDArray, необходимо использовать функцию .shape, как в NumPy:

x = nd.empty((2, 7))
x.shape

Наконец, если вы хотите найти общее количество элементов в NDArray, используйте функцию .size:

x.size

Операции в NDArray точно такие же, как в NumPy, поэтому мы не будем здесь подробно останавливаться на них. Содержимое также доступно таким же образом, через индексирование и нарезку.

Если вы хотите преобразовать NDArray в более знакомую структуру данных из пакета NumPy, вы можете использовать функцию asnumpy():

y = x.asnumpy()

Обратное можно достичь с помощью функции array():

z = nd.array(y)

Одна из отличительных особенностей NDArrays заключается в том, что они могут присваивать разные вычислительные контексты разным массивам — либо на CPU, либо на GPU, подключенном к вашей машине (это называется «контекст» при обсуждении NDArrays). Это стало возможным благодаря параметру ctx во всех соответствующих функциях пакета. Например, при создании пустого массива нулей, который вы хотите присвоить первому GPU, просто введите:

a = nd.zeros(shape=(5,5), ctx=mx.gpu(0))

Конечно, данные, присвоенные конкретному вычислительному блоку, не закреплены навсегда. Легко скопировать данные в другое место, связанное с другим вычислительным блоком, используя функцию copyto():

y = x.copyto(mx.gpu(1)) # copy the data of
NDArray x to the 2nd GPU

Вы можете узнать контекст переменной с помощью атрибута .context:

print(x.context)

Часто удобнее определить контекст как данных, так и моделей, используя для каждого отдельную переменную. Например, предположим, что ваш проект глубокого обучения использует данные, которые вы хотите обрабатывать на CPU, и модель, которую вы предпочитаете обрабатывать на первом GPU. В этом случае вы можете набрать что-то вроде:

DataCtx = mx.cpu()
ModelCtx = mx.gpu(0)

Пакет MXNet в Python

Пакет MXNet (или «mxnet», с нижним регистром при наборе в Python) является очень надежной и самодостаточной библиотекой в Python. MXNet предоставляет возможности глубокого обучения через фреймворк MXNet.

Импорт этого пакета в Python довольно прост:

import mxnet as mx

Если вы хотите выполнить некоторые дополнительные процессы, которые сделают использование MXNet еще лучше, настоятельно рекомендуется сначала установить следующие пакеты на свой компьютер:

  • graphviz (версия 0.8.1 или новее)
  • requests (версия 2.18.4 или новее)
  • numpy (версия 1.13.3 или новее)

Вы можете узнать больше о пакете MXNet через соответствующий репозиторий на GitHub.8

MXNet в действии

Теперь давайте посмотрим, что мы можем сделать с MXNet, используя Python, на образе Docker со всем необходимым программным обеспечением, уже установленным. Мы начнем с краткого описания наборов данных, которые будем использовать, а затем перейдем к паре конкретных приложений глубокого обучения, использующих эти данные (а именно классификация и регрессия). Освоив их, вы сможете самостоятельно изучить более продвинутые системы глубокого обучения этого фреймворка.

Описание наборов данных

В этом разделе мы представим два синтетических набора данных, которые мы подготовили для демонстрации методов классификации и регрессии на них. Первый набор данных предназначен для классификации, а второй - для регрессии. Причина, по которой мы используем синтетические наборы данных в этих упражнениях, заключается в максимальном понимании данных, чтобы мы могли оценивать результаты систем глубокого обучения независимо от качества данных.

Первый набор данных содержит 4 переменные: 3 признака и 1 переменная-метка. С 250 000 точек данных он достаточно велик для работы сети глубокого обучения.

с ним. Его небольшая размерность делает его идеальным для визуализации (см.Рисунок 2). Он также сделан так, чтобы иметь большую степень нелинейности, что делает его хорошей задачей для любой модели данных (хотя и не слишком сложной для системы глубокого обучения). Кроме того, классы 2 и 3 этого набора данных достаточно близки, чтобы вызывать путаницу, но при этом различаются. Это делает их хорошим вариантом для применения кластеризации, как мы увидим позже.

Картинка в статье
Рисунок 2: Графическое изображение первого набора данных, использованного в этих примерах. Различные цвета соответствуют разным классам набора данных. Хотя три класса четко выделяются, определение, к какому из них принадлежит неизвестная точка данных, является нелинейным. Это связано с наличием сферического класса, что делает всю проблему достаточно сложной, чтобы сделать подход глубокого обучения актуальным.

Второй набор данных несколько больше, содержащий 21 переменную — 20 из которых являются признаками, используемыми для предсказания последней, которая является целевой переменной. С 250 000 точек данных он снова идеально подходит для системы глубокого обучения. Обратите внимание, что только 10 из 20 признаков релевантны целевой переменной (которая является комбинацией этих 10). К данным добавлен небольшой шум, чтобы сделать

всю проблему немного более сложной. Оставшиеся 10 признаков — это просто случайные данные, которые должны быть отфильтрованы моделью глубокого обучения. Релевантны они или нет, этот набор данных имеет достаточно признаков, чтобы сделать применение уменьшения размерности целесообразным. Естественно, из-за его размерности мы не можем построить график этого набора данных.

Загрузка набора данных в NDArray

Теперь давайте посмотрим, как мы можем загрузить набор данных в MXNet, чтобы затем обработать его с помощью модели глубокого обучения. Сначала давайте установим некоторые параметры:

DataCtx = mx.cpu() # assign context of the data
used
BatchSize = 64 # batch parameter for dataloader
object
r = 0.8 # ratio of training data
nf = 3 # number of features in the dataset (for
the classification problem)

Теперь мы можем импортировать данные так, как мы обычно делаем в традиционном DS-проекте, но на этот раз сохранить их в NDArrays вместо массивов Pandas или NumPy:

with open("../data/data1.csv") as f:
data_raw = f.read()
lines = data_raw.splitlines() # split the data
into separate lines
ndp = len(lines) # number of data points
X = nd.zeros((ndp, nf), ctx=data_ctx)
Y = nd.zeros((ndp, 1), ctx=data_ctx)
for i, line in enumerate(lines):
tokens = line.split()
Y[i] = int(tokens[0])
for token in tokens[1:]:
index = int(token[:-2]) - 1
X[i, index] = 1

Теперь мы можем разделить данные на обучающий и тестовый наборы, чтобы использовать их как для построения, так и для проверки нашей модели классификации:

import numpy as np # we’ll be needing this
package as well
n = np.round(N * r) # number of training data
points
train = data[:n, ] # training set partition
test = data[(n + 1):,] # testing set partition
data_train =
gluon.data.DataLoader(gluon.data.ArrayDataset(tra
in[:,:3], train[:,3]), batch_size=BatchSize,
shuffle=True)
data_test =
gluon.data.DataLoader(gluon.data.ArrayDataset(tes
t[:,:3], test[:,3]), batch_size=BatchSize,
shuffle=True)

Затем нам потребуется повторить тот же процесс для загрузки второго набора данных — на этот раз используя data2.csv в качестве исходного файла. Также, чтобы избежать путаницы с объектами загрузчиков данных первого набора данных, вы можете назвать новые загрузчики данных data_train2 и data_test2, соответственно.

Классификация

Теперь давайте исследуем, как мы можем использовать эти данные для построения системы MLP, способной различать различные классы внутри подготовленных данных. Для начала, давайте посмотрим, как это сделать, используя сам пакет mxnet; затем мы рассмотрим, как то же самое можно достичь с помощью Gluon.

Сначала определим некоторые константы, которые будем использовать позже для построения, обучения и тестирования сети MLP:

nhn = 256 # number of hidden nodes for each layer
WeightScale = 0.01 # scale multiplier for weights
ModelCtx = mx.cpu() # assign context of the model
itself
no = 3 # number of outputs (classes)
ne = 10 # number of epochs (for training)

Далее инициализируем параметры сети (веса и смещения) для первого слоя:

lr = 0.001 # learning rate (for training)
sc = 0.01 # smoothing constant (for training)
ns = test.shape[0] # number of samples (for
testing)
W1 = nd.random_normal(shape=(nf, nhn),
scale=WeightScale, ctx=ModelCtx)
b1 = nd.random_normal(shape=nhn,
scale=WeightScale, ctx=ModelCtx)

И сделаем то же самое для второго слоя:

W2 = nd.random_normal(shape=(nhn, nhn),
scale=WeightScale, ctx=ModelCtx)
b2 = nd.random_normal(shape=nhn,
scale=WeightScale, ctx=ModelCtx)

Затем инициализируем выходной слой и объединим все параметры в единую структуру данных под названием params:

W3 = nd.random_normal(shape=(nhn, no),
scale=WeightScale, ctx=ModelCtx)
b3 = nd.random_normal(shape=no,
scale=WeightScale, ctx=ModelCtx)
params = [W1, b1, W2, b2, W3, b3]

Наконец, выделим немного места для градиента для каждого из этих параметров:

for param in params:
param.attach_grad()

Помните, что без нелинейных функций в нейронах MLP вся система была бы слишком рудиментарной, чтобы быть полезной. Мы будем использовать функции ReLU и Softmax в качестве функций активации для нашей

system:
def relu(X): return nd.maximum(X,
nd.zeros_like(X))
def softmax(y_linear):
exp = nd.exp(y_linear - nd.max(y_linear))
partition = nd.nansum(exp, axis=0,
exclude=True).reshape((-1, 1))
return exp / partition

Обратите внимание, что функция Softmax будет использоваться в выходных нейронах, в то время как функция ReLU будет использоваться во всех остальных нейронах сети.

В качестве функции стоимости сети (или, другими словами, функции приспособленности метода оптимизации, лежащего в основе), мы будем использовать функцию кросс-энтропии:

def cross_entropy(yhat, y): return - nd.nansum(y
* nd.log(yhat), axis=0, exclude=True)

Чтобы сделать всю систему более эффективной, мы можем объединить функции softmax и кросс-энтропии в одну, следующим образом:

def softmax_cross_entropy(yhat_linear, y):
return - nd.nansum(y *
nd.log_softmax(yhat_linear), axis=0,
exclude=True)

После всего этого мы теперь можем определить функцию всей нейронной сети, основанную на вышеуказанной архитектуре:

def net(X):
h1_linear = nd.dot(X, W1) + b1
h1 = relu(h1_linear)
h2_linear = nd.dot(h1, W2) + b2
h2 = relu(h2_linear)
yhat_linear = nd.dot(h2, W3) + b3
return yhat_linear

Метод оптимизации для обучения системы также должен быть определен. В данном случае мы будем использовать форму градиентного спуска:

def SGD(params, lr):
for param in params:
param[:] = param - lr * param.grad
return param

Для целей этого примера мы будем использовать простую метрику оценки для модели: точность. Конечно, это необходимо определить сначала:

def evaluate_accuracy(data_iterator, net):
numerator = 0.
denominator = 0.
for i, (data, label) in
enumerate(data_iterator):
data =
data.as_in_context(model_ctx).reshape((-1, 784))
label = label.as_in_context(model_ctx)
output = net(data)
predictions = nd.argmax(output, axis=1)
numerator += nd.sum(predictions == label)
denominator += data.shape[0]
return (numerator / denominator).asscalar()

Теперь мы можем обучить систему следующим образом:

Now we can train the system as follows:
for e in range(epochs):
cumulative_loss = 0
for i, (data, label) in
enumerate(train_data):
data =
data.as_in_context(model_ctx).reshape((-1, 784))
label = label.as_in_context(model_ctx)
label_one_hot = nd.one_hot(label, 10)
with autograd.record():
output = net(data)
loss = softmax_cross_entropy(output,
label_one_hot)
loss.backward()
SGD(params, learning_rate)
cumulative_loss +=
nd.sum(loss).asscalar()
test_accuracy = evaluate_accuracy(test_data,
net)
train_accuracy =
evaluate_accuracy(train_data, net)
print("Epoch %s. Loss: %s, Train_acc %s,
Test_acc %s" %
(e, cumulative_loss/num_examples,
train_accuracy, test_accuracy))

Наконец, мы можем использовать систему для получения некоторых предсказаний, используя следующий код:

def model_predict(net, data):
output = net(data)
return nd.argmax(output, axis=1)
SampleData = mx.gluon.data.DataLoader(data_test,
ns, shuffle=True)
for i, (data, label) in enumerate(SampleData):
data = data.as_in_context(ModelCtx)
im = nd.transpose(data,(1,0,2,3))
im = nd.reshape(im,(28,10*28,1))
imtiles = nd.tile(im, (1,1,3))
plt.imshow(imtiles.asnumpy())
plt.show()
pred=model_predict(net,data.reshape((-1,784)))
print('model predictions are:', pred)
print('true labels :', label)
break

Если вы запустите приведенный выше код (желательно в среде Docker), вы увидите, что эта простая система MLP хорошо справляется с

предсказанием классов некоторых неизвестных точек данных — даже если границы классов сильно нелинейны. Экспериментируйте с этой системой больше и посмотрите, как можно еще больше улучшить ее производительность, используя фреймворк MXNet.

Теперь мы увидим, как значительно упростить всё это, используя интерфейс Gluon. Сначала давайте определим класс Python для охвата некоторых распространенных случаев многослойных перцептронов, преобразуя объект "gluon.Block" в нечто, что можно использовать для постепенного построения нейронной сети, состоящей из нескольких слоев (также известных как MLP):

class MLP(gluon.Block):
def __init__(self, **kwargs):
super(MLP, self).__init__(**kwargs)
with self.name_scope():
self.dense0 = gluon.nn.Dense(64) # architecture
of 1st layer (hidden)
self.dense1 = gluon.nn.Dense(64) # architecture
of 2nd layer (hidden)
self.dense2 = gluon.nn.Dense(3) # architecture
of 3rd layer (output)
def forward(self, x): # a function enabling an
MLP to process data (x) by passing it forward
(towards the output layer)
x = nd.relu(self.dense0(x)) # outputs of
first hidden layer
x = nd.relu(self.dense1(x)) # outputs of
second hidden layer
x = self.dense2(x) # outputs of final layer
(output)
return x

Конечно, это всего лишь пример того, как вы можете определить MLP с использованием Gluon, а не универсальное решение. Возможно, вы захотите определить класс MLP по-другому, поскольку используемая архитектура повлияет на производительность системы. (Это особенно верно для сложных задач, где дополнительные скрытые слои были бы полезны.) Однако, если то, что следует далее, кажется вам слишком сложным, и у вас нет времени,

усвоить теорию систем глубокого обучения, рассмотренную в Главе 1, вы можете использовать объект MLP, подобный описанному выше, для своего проекта.

Поскольку системы глубокого обучения редко бывают такими компактными, как описанный выше MLP, и поскольку нам часто необходимо добавлять больше слоев (что было бы громоздким при использовании вышеупомянутого подхода), обычно используется другой класс под названием Sequential. После того как мы определим количество нейронов в каждом скрытом слое и укажем функцию активации для этих нейронов, мы можем построить MLP, подобно лестнице, где каждый шаг представляет собой один слой в MLP:

nhn = 64 # number of hidden neurons (in each
layer)
af = “relu” # activation function to be used in
each neuron
net = gluon.nn.Sequential()
with net.name_scope():
net.add(gluon.nn.Dense(nhn , activation=af))
net.add(gluon.nn.Dense(nhn , activation=af))
net.add(gluon.nn.Dense(no))

Это заботится об архитектуре за нас. Чтобы сделать вышеуказанную сеть функциональной, нам сначала нужно ее инициализировать:

sigma = 0.1 # sigma value for distribution of
weights for the ANN connections
ModelCtx = mx.cpu()
lr = 0.01 # learning rate
oa = ‘sgd’ # optimization algorithm
net.collect_params().initialize(mx.init.Normal(si
gma=sigma), ctx=ModelCtx)
softmax_cross_entropy =
gluon.loss.SoftmaxCrossEntropyLoss()
trainer = gluon.Trainer(net.collect_params(), oa,
{‘learning_rate’: lr})
ne = 10 # number of epochs for training

Далее необходимо определить, как мы будем оценивать прогресс сети, с помощью функции оценки. Для простоты будем использовать стандартную метрику точности:

def AccuracyEvaluation(iterator, net):
acc = mx.metric.Accuracy()
for i, (data, label) in enumerate(iterator):
data =
data.as_in_context(ModelCtx).reshape((-1, 3))
label = label.as_in_context(ModelCtx)
output = net(data)
predictions = nd.argmax(output, axis=1)
acc.update(preds=predictions,
labels=label)
return acc.get()[1]

Наконец, пришло время обучить и протестировать MLP, используя вышеупомянутые настройки:

for e in range(ne):
cumulative_loss = 0
for i, (data, label) in
enumerate(train_data):
data =
data.as_in_context(ModelCtx).reshape((-1, 784))
label = label.as_in_context(ModelCtx)
with autograd.record():
output = net(data)
loss = softmax_cross_entropy(output,
label)
loss.backward()
trainer.step(data.shape[0])
cumulative_loss +=
nd.sum(loss).asscalar()
train_accuracy =
AccuracyEvaluation(train_data, net)
test_accuracy = AccuracyEvaluation(test_data,
net)
print("Epoch %s. Loss: %s, Train_acc %s,
Test_acc %s" %
(e, cumulative_loss/ns, train_accuracy,
test_accuracy))

Запуск приведенного выше кода должен дать результаты, аналогичные результатам стандартных команд mxnet.

Чтобы упростить задачу, мы будем полагаться на интерфейс Gluon в следующем примере. Тем не менее, мы по-прежнему рекомендуем поэкспериментировать со стандартными функциями mxnet впоследствии, если вы хотите разработать свои собственные архитектуры (или лучше понять теорию глубокого обучения).

Регрессия

Создание системы регрессии MLP похоже на создание системы классификации, но с некоторыми различиями. В случае регрессии регрессия будет проще, поскольку регрессоры обычно архитектурно легче, чем классификаторы. Для этого примера мы будем использовать второй набор данных.

Сначала импортируем необходимые классы из пакета mxnet и установим контекст для модели:

import mxnet as mx
from mxnet import nd, autograd, gluon
ModelCtx = mx.cpu()

Для загрузки данных в модель мы будем использовать загрузчики данных, созданные ранее (data_train2 и data_test2). Теперь определим некоторые базовые настройки и постепенно построим сеть глубокого обучения:

nf = 20 # we have 20 features in this dataset
sigma = 1.0 # sigma value for distribution of
weights for the ANN connections
net = gluon.nn.Dense(1, in_units=nf) # the “1”
here is the number of output neurons, which is 1
in regression

Теперь инициализируем сеть случайными значениями для весов и смещений:

net.collect_params().initialize(mx.init.Normal(si
gma=sigma), ctx=ModelCtx)

Как и в любой другой системе глубокого обучения, нам необходимо определить функцию потерь. Используя эту функцию, система понимает, насколько стоит каждая ошибка от значений целевой переменной. В то же время, функции потерь также могут учитывать сложность моделей (поскольку если модели слишком сложны, они могут привести к переобучению):

square_loss = gluon.loss.L2Loss()

Теперь пришло время обучить сеть, используя имеющиеся данные. После определения некоторых важных параметров (как и в случае классификации), мы можем создать цикл для обучения сети:

ne = 10 # number of epochs for training
loss_sequence = [] # cumulative loss for the
various epochs
nb = ns / BatchSize # number of batches
for e in range(ne):
cumulative_loss = 0
for i, (data, label) in
enumerate(train_data): # inner loop
data = data.as_in_context(ModelCtx)
label = label.as_in_context(ModelCtx)
with autograd.record():
output = net(data)
loss = square_loss(output, label)
loss.backward()
trainer.step(BatchSize)
CumulativeLoss +=
nd.mean(loss).asscalar()
print("Epoch %s, loss: %s" % (e,
CumulativeLoss / ns))
loss_sequence.append(CumulativeLoss)

Если вы хотите просмотреть параметры модели, вы можете сделать это, собрав их в структуру словаря:

params = net.collect_params()
for param in params.values():
print(param.name, param.data())

Вывод параметров может показаться не слишком полезным, так как их обычно слишком много, и особенно когда мы добавляем новые слои в систему, что мы делаем следующим образом:

net.add(gluon.nn.Dense(nhn))

где nhn — количество нейронов в этом дополнительном скрытом слое. Обратите внимание, что сеть требует выходного слоя с одним нейроном, поэтому обязательно добавляйте любые дополнительные слои между входным и выходным слоями.

Создание контрольных точек для моделей, разработанных в MXNet

Поскольку обучение системы может занять некоторое время, возможность сохранения и загрузки моделей и данных глубокого обучения с помощью этого фреймворка является критически важной. Мы должны создать «контрольные точки» в нашей работе, чтобы мы могли продолжить с того места, где остановились, не создавая сеть с нуля каждый раз. Это достигается следующим процессом.

Сначала импортируйте все необходимые пакеты и классы, а затем определите параметр контекста:

import mxnet as mx
from mxnet import nd, autograd, gluon
import os
ctx = mx.cpu() # context for NDArrays

Затем мы сохраним данные, но сначала поместим их в словарь:

dict = {"X": X, "Y": Y}

Теперь установим имя файла и сохраним его:

filename = "test.dat"
nd.save(filename, dict)

Мы можем убедиться, что всё сохранено правильно, загрузив контрольную точку следующим образом:

Z = nd.load(filename)
print(Z)

При использовании gluon существует ярлык для сохранения всех параметров разработанной нами сети глубокого обучения. Это функция save_params():

filename = "MyNet.params"
net.save_params(filename)

Однако, чтобы восстановить сеть глубокого обучения, вам потребуется воссоздать исходную архитектуру сети, а затем загрузить параметры исходной сети из соответствующего файла:

net2 = gluon.nn.Sequential()with
net2.name_scope():
net2.add(gluon.nn.Dense(num_hidden,
activation=”relu”))
net2.add(gluon.nn.Dense(num_hidden,
activation=”relu”))
net2.add(gluon.nn.Dense(num_outputs))
net2.load_params(filename, ctx=ctx)

Лучше всего сохранять свою работу в различных частях конвейера и давать файлам контрольных точек описательные имена. Важно также помнить, что у нас нет опции «отмены обучения» и, вероятно, оптимальная производительность достигается до завершения фазы обучения. Из-за этого мы можем захотеть создавать контрольные точки после каждой эпохи обучения, чтобы мы могли вернуться к ней, когда обнаружим, в какой момент достигается оптимальная производительность.

Более того, чтобы компьютер мог правильно интерпретировать эти файлы при загрузке их в вашу среду программирования, вам потребуется класс nd из mxnet в памяти, независимо от того, какой язык программирования вы используете.

Советы по MXNet

Фреймворк MXNet — это очень надежная и универсальная платформа для различных систем глубокого обучения. Хотя мы продемонстрировали его функциональность в Python, он одинаково мощен при использовании с другими языками программирования.

Кроме того, интерфейс Gluon — полезное дополнение. Если вы новичок в приложениях глубокого обучения, мы рекомендуем использовать Gluon как основной инструмент при работе с фреймворком MXNet. Это не означает, что сам фреймворк ограничен Gluon, поскольку пакет mxnet универсален и надежен на различных платформах программирования.

Более того, в этой главе мы рассмотрели только основы MXNet и Gluon. Изучение всех деталей этих надежных систем заняло бы целую книгу! Узнайте больше о деталях интерфейса Gluon в руководстве Straight Dope, которое является частью документации MXNet.9

Наконец, примеры в этой главе выполняются в контейнере Docker; поэтому вы можете испытывать некоторую задержку. При разработке системы глубокого обучения на компьютерном кластере, конечно, это происходит значительно быстрее.

Резюме

  • MXNet - это фреймворк глубокого обучения, разработанный Apache. Он демонстрирует простоту использования, гибкость и высокую скорость, среди прочих преимуществ. Всё это делает MXNet привлекательным вариантом для глубокого обучения на различных языках программирования, включая Python, Julia, Scala и R.
  • Модели MXNet могут быть развернуты на всех типах вычислительных систем, включая интеллектуальные устройства. Это достигается экспортом их в виде единого файла, который затем выполняется этими устройствами.
  • Gluon — это пакет, предоставляющий простой интерфейс для всей вашей работы с глубоким обучением с использованием MXNet. Его основные преимущества включают простоту использования, отсутствие значительных накладных расходов, возможность обрабатывать динамические графы для ваших моделей ANN и гибкость.
  • NDArrays являются полезными структурами данных при работе с фреймворком MXNet. Их можно импортировать в виде модулей из
  • пакета mxnet как nd. Они похожи на массивы NumPy, но более универсальны и эффективны при работе с приложениями глубокого обучения.
  • Пакет mxnet является API Python для фреймворка MXNet и содержит множество модулей для построения и использования систем глубокого обучения.
  • Данные могут быть загружены в MXNet через NDArray, непосредственно из файла данных; а затем создать объект dataloader для подачи данных в модель, построенную впоследствии.
  • Классификация в MXNet включает создание MLP (или другой сети глубокого обучения), его обучение и использование для предсказания неизвестных данных, выделяя по одному нейрону для каждого класса в наборе данных. Классификация значительно проще при использовании Gluon.
  • Регрессия в MXNet похожа на классификацию, но выходной слой имеет один нейрон. Также необходимо принимать дополнительные меры, чтобы система не переобучалась; поэтому мы часто используем некоторую функцию регуляризации, например L2.
  • Создание контрольных точек проекта в MXNet включает сохранение модели и любых других соответствующих данных в NDArrays, чтобы вы могли получить их в другое время. Это также полезно для обмена работой с другими для целей обзора.
  • Помните, что MXNet, как правило, быстрее, чем на контейнере Docker, используемом в примерах этой главы, и что он одинаково полезен и надежен на других языках программирования.

https://bit.ly/2uweNb0.

https://github.com/apache/incubator-mxnet.

http://gluon.mxnet.io/index.html.

Предыдущая глава    Следующая глава