MXNet: A flexible and efficient library for deep learning.
Это МХНетОфициальный сайтВведение: «MXNet — это гибкая и эффективная библиотека глубокого обучения».
MXNet — одна из трех основных сред глубокого обучения:
- TensorFlow: поддерживается Google, его упрощенная версияKeras;
- PyTorch: поддержка Facebook, его промышленная версияCaffe2;
- MXNet: нейтральный проект-инкубатор Apache, также выбранный AWS в качестве официальной платформы DL;
Преимущество MXNet в том, что один из его разработчиков, Ли Му, является китайцем ??, и имеет языковые преимущества (китайский) в продвижении MXNet, что способствует обучению отечественных разработчиков. В то же время рекомендуется, чтобы Ли Му записалУчебное видео,очень хороший.
Высокоуровневый интерфейс MXNet — Gluon. Gluon поддерживает как гибкие динамические графики, так и эффективные статические графики. Он не только сохраняет простоту использования динамических графиков, но также обладает высокой производительностью статических графиков. Это также представлено на официальном Веб-сайт.flexibleиefficientисточник. В то же время MXNet также имеет большое количество передовых алгоритмов в академических кругах, что удобно для переноса в промышленность. Я надеюсь, что команда MXNet продолжит усердно работать и будет в авангарде конкурса фреймворков глубокого обучения.
Поэтому мастерMXNet/Gluonнеобходимый.
В этой статье используется глубокое обучениеМногослойный персептрон(Многослойные персептроны) является основой алгоритма, а набор данных выбираетсяMNIST, в котором представлены технические детали MXNet.
этой статьиисходный код: https://GitHub.com/spike king/gluon-tutorial
набор данных
В виртуальной среде (Virtual Env) просто используйте pip для установки MXNet:
pip install mxnet
Если скорость загрузки низкая, рекомендуется использоватьАли КлаудИсточник пипи:
-i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com
MNISTЭто известная библиотека распознавания рукописных цифр, которая содержит рукописные символы из 10 цифр, например от 0 до 9, а размер изображения представляет собой изображение в градациях серого 28 * 28. Цель состоит в том, чтобы определить правильные цифры в соответствии с изображением.
Библиотека MNIST упакована в MXNet какМНИСТ класс, данные хранятся в.mxnet/datasets/mnist
середина. Если загрузка данных MNIST идет медленно, вы можетеMNISTСкачайте его с официального сайта и поместите в папку mnist. В классе МНИСТ:
- параметр
train
: Является ли это обучающими данными, где true — это обучающие данные, а false — тестовые данные; - параметр
transform
: функции преобразования данных, лямбда-выражения, преобразование данных и меток в указанные типы данных;
Исходный код:
# 参数train
if self._train:
data, label = self._train_data, self._train_label
else:
data, label = self._test_data, self._test_label
# 参数transform
if self._transform is not None:
return self._transform(self._data[idx], self._label[idx])
return self._data[idx], self._label[idx]
В MXNet класс загрузки данных инкапсулирован какКласс DataLoader, режим итератора, итеративно выводит тот же набор выборок, что и количество пакетов. В DataLoader,
- параметр
dataset
: источник данных, например MNIST; - параметр
batch_size
: количество пакетов в процессе обучения и указанное количество образцов выводятся в итерациях; - параметр
shuffle
: Перетасовать ли карты, то есть перетасовать данные, эта операция вообще требуется во время обучения.
Тест итератора, количество выходных выборок (1-е измерение) каждый раз совпадает с указанным количеством пакетов:
for data, label in train_data:
print(data.shape) # (64L, 28L, 28L, 1L)
print(label.shape) # (64L,)
break
существуетload_data()
В методе выводятся обучающие и тестовые данные, тип данных — число с плавающей запятой от 0 до 1 (значение серого, деленное на 255), а тип метки — также число с плавающей запятой.
Выполнение:
def load_data(self):
def transform(data, label):
return data.astype(np.float32) / 255., label.astype(np.float32)
train_data = DataLoader(MNIST(train=True, transform=transform),
self.batch_size, shuffle=True)
test_data = DataLoader(MNIST(train=False, transform=transform),
self.batch_size, shuffle=False)
return train_data, test_data
Модель
Сетевая модель использует стиль Gluon в MXNet:
- Создайте
Sequential()
Sequence, Sequential — это контейнер всех операционных единиц; - Добавьте полностью подключенный блок Dense, единицы параметра — это количество выходных единиц, а активация параметра — функция активации;
- Параметры инициализации:
- init — источник данных, класс Normal — нормальное распределение, а sigma — стандартное отклонение нормального распределения;
- ctx — это контекст, который означает, что обновление параметра в обучении использует CPU или GPU, например, mx.cpu();
Класс Sequential от Gluon похож на другие фреймворки глубокого обучения.чтобыСоедините различные операционные блоки для формирования различных сетевых структур.Каждому уровню нужно только установить размерность вывода, размерность ввода передается через предыдущий уровень, а матрица преобразования автоматически рассчитывается внутри.
выполнить:
def model(self):
num_hidden = 64
net = gluon.nn.Sequential()
with net.name_scope():
net.add(gluon.nn.Dense(units=num_hidden, activation="relu"))
net.add(gluon.nn.Dense(units=num_hidden, activation="relu"))
net.add(gluon.nn.Dense(units=self.num_outputs))
net.collect_params().initialize(init=mx.init.Normal(sigma=.1), ctx=self.model_ctx)
print(net) # 展示模型
return net
в,net.name_scope()
Автоматически добавляйте имена к единицам действия в Sequential.
Визуализация модели
Используйте print() напрямую для печати структуры модели, напримерprint(net)
:
Sequential(
(0): Dense(None -> 64, Activation(relu))
(1): Dense(None -> 64, Activation(relu))
(2): Dense(None -> 10, linear)
)
или, используя немного более сложныйjupyterЧтобы нарисовать модель, установите пакет jupyter (Python 2.x):
pip install ipython==5.3.0
pip install jupyter==1.0.0
Запустите службу jupyter и получите доступhttp://localhost:8888/
:
jupyter notebook
новыйPython 2
файл для написания кода для рисования сети. Стиль кода состоит в том, чтобы добавить «логику рисования» после существующей модели, вызываяplot_network()
рисовать. Если вы замените класс Sequential классом HybridSequential, эффективность рисования можно повысить, а эффект рисования не изменится без замены.
Сетевая модель и логика рисования:
import mxnet as mx
from mxnet import gluon
num_hidden = 64
net = gluon.nn.HybridSequential()
with net.name_scope():
net.add(gluon.nn.Dense(num_hidden, activation="relu"))
net.add(gluon.nn.Dense(num_hidden, activation="relu"))
net.add(gluon.nn.Dense(10))
# 绘制逻辑
net.hybridize()
net.collect_params().initialize()
x = mx.sym.var('data')
sym = net(x)
mx.viz.plot_network(sym)
Изображение эффекта:
тренироваться
Перед обучением загрузите данные и создайте сеть.
train_data, test_data = self.load_data() # 训练和测试数据
net = self.model() # 模型
Далее создадим интерфейс для кросс-энтропииsoftmax_cross_entropy
, создать трейнерtrainer
.
К параметрам трейнера относятся: параметры в сети, оптимизатор, параметры оптимизатора и т.д.
epochs = 10
smoothing_constant = .01
num_examples = 60000
softmax_cross_entropy = gluon.loss.SoftmaxCrossEntropyLoss() # 交叉熵
trainer = gluon.Trainer(params=net.collect_params(),
optimizer='sgd',
optimizer_params={'learning_rate': smoothing_constant})
Эпоха цикла для обучения сетевой модели:
- от итератора
train_data
источник, получить пакетные данные и метки: - Среда выполнения ctx указанных данных и метки — ЦП или ГП, а расширенные данные — 1 строка;
- Автоматический расчет градиента
autograd.record()
, сеть прогнозирует данные, выводит результат и вычисляет потерю перекрестной энтропии; - Для получения обратного распространения потерь шагами настройки тренера являются количество пакетов;
- существует
cumulative_loss
, потери каждой партии накапливаются, и рассчитывается общая потеря; - После обучения эпохи рассчитайте точность тестовых и обучающих данных;
Продолжайте цикл, пока выполнение не завершит все эпохи.
Осуществление обучения:
for e in range(epochs):
cumulative_loss = 0 # 累积的
for i, (data, label) in enumerate(train_data):
data = data.as_in_context(self.model_ctx).reshape((-1, 784)) # 数据
label = label.as_in_context(self.model_ctx) # 标签
with autograd.record(): # 梯度
output = net(data) # 输出
loss = softmax_cross_entropy(output, label) # 输入和输出计算loss
loss.backward() # 反向传播
trainer.step(data.shape[0]) # 设置trainer的step
cumulative_loss += nd.sum(loss).asscalar() # 计算全部损失
test_accuracy = self.__evaluate_accuracy(test_data, net)
train_accuracy = self.__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))
в интерфейсе предсказанияevaluate_accuracy()
середина:
- Создайте класс Accuracy для статистической точности;
- Итеративно выводить пакеты данных и меток;
- Прогнозировать вероятность различных категорий данных и выбирать максимальную вероятность (argmax) в качестве категории;
- пройти через
acc.update()
точность обновления;
Наконец, верните значение точности, которое является вторым измерением accacc[1]
, а первая размерность соотв.acc[0]
это название акк.
def __evaluate_accuracy(self, data_itertor, net):
acc = mx.metric.Accuracy() # 准确率
for i, (data, label) in enumerate(data_iterator):
data = data.as_in_context(self.model_ctx).reshape((-1, 784))
label = label.as_in_context(self.model_ctx)
output = net(data) # 预测结果
predictions = nd.argmax(output, axis=1) # 类别
acc.update(preds=predictions, labels=label) # 更新概率和标签
return acc.get()[1] # 第1维是数据名称,第2维是概率
Эффект:
Epoch 0. Loss: 1.2743850797812144, Train_acc 0.846283333333, Test_acc 0.8509
Epoch 1. Loss: 0.46071574948628746, Train_acc 0.884366666667, Test_acc 0.8892
Epoch 2. Loss: 0.37149955205917357, Train_acc 0.896466666667, Test_acc 0.9008
Epoch 3. Loss: 0.3313815038919449, Train_acc 0.908366666667, Test_acc 0.9099
Epoch 4. Loss: 0.30456133014361064, Train_acc 0.915966666667, Test_acc 0.9172
Epoch 5. Loss: 0.2827877395868301, Train_acc 0.919466666667, Test_acc 0.9214
Epoch 6. Loss: 0.2653073514064153, Train_acc 0.925433333333, Test_acc 0.9289
Epoch 7. Loss: 0.25018166739145914, Train_acc 0.92965, Test_acc 0.9313
Epoch 8. Loss: 0.23669789231618246, Train_acc 0.933816666667, Test_acc 0.9358
Epoch 9. Loss: 0.22473177655935286, Train_acc 0.934716666667, Test_acc 0.9337
GPU
Для глубокого обучения использование графического процессора может ускорить процесс обучения сети, а MXNet также поддерживает использование графического процессора для обучения сети.
Чтобы проверить Cuda-версию сервера, команда:nvcc --version
, который используется для определения версии графического процессора для загрузки MXNet.
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2016 NVIDIA Corporation
Built on Sun_Sep__4_22:14:01_CDT_2016
Cuda compilation tools, release 8.0, V8.0.44
Тогда текущая версия Cuda сервера — 8.0.
Преобразование MXNet из версии ЦП вверсия графического процессора, удалитьmxnet
,Установитьmxnet-cu80
.
pip uninstall mxnet
pip install mxnet-cu80
После установки версии GPU выполните следующий код в консоли Python, чтобы убедиться, что можно использовать библиотеку GPU MXNet.
>>> import mxnet as mx
>>> a = mx.nd.ones((2, 3), mx.gpu())
>>> b = a * 2 + 1
>>> b.asnumpy()
array([[ 3., 3., 3.],
[ 3., 3., 3.]], dtype=float32)
Чтобы проверить количество графических процессоров, команда:nvidia-smi
:
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 375.26 Driver Version: 375.26 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 TITAN X (Pascal) Off | 0000:02:00.0 Off | N/A |
| 28% 49C P2 84W / 250W | 12126MiB / 12189MiB | 25% Default |
+-------------------------------+----------------------+----------------------+
| 1 TITAN X (Pascal) Off | 0000:03:00.0 Off | N/A |
| 24% 39C P2 57W / 250W | 12126MiB / 12189MiB | 33% Default |
+-------------------------------+----------------------+----------------------+
| 2 TITAN X (Pascal) Off | 0000:83:00.0 Off | N/A |
| 25% 41C P2 58W / 250W | 12126MiB / 12189MiB | 37% Default |
+-------------------------------+----------------------+----------------------+
| 3 TITAN X (Pascal) Off | 0000:84:00.0 Off | N/A |
| 23% 31C P2 53W / 250W | 11952MiB / 12189MiB | 2% Default |
+-------------------------------+----------------------+----------------------+
Тогда количество графических процессоров на текущем сервере равно 4.
Установите параметр environment ctx в список графических процессоров, т.е.[mx.gpu(0), mx.gpu(1), ...]
.
GPU_COUNT = 4
ctx = [mx.gpu(i) for i in range(GPU_COUNT)]
Используйте графический процессор для инициализации параметров параметра initialize() в сети, а затем создайте тренера.
net = self.model() # 模型
net.collect_params().initialize(init=mx.init.Normal(sigma=.1), ctx=ctx)
smoothing_constant = .01
trainer = gluon.Trainer(params=net.collect_params(),
optimizer='sgd',
optimizer_params={'learning_rate': smoothing_constant})
Пройдите через 10 эпох, чтобы обучить модель,train_data
иvalid_data
— это итератор, который каждый раз выводит пакетный набор образцов. существуетtrain_batch()
, передать пакет пакетных данных, список среды графического процессора ctx, сетевую сеть и тренер по очереди; вvalid_batch()
, аналогично обучению, за исключением того, что трейнер не проходит.
epochs = 10
for e in range(epochs):
start = time()
for batch in train_data:
self.train_batch(batch, ctx, net, trainer)
nd.waitall() # 等待所有异步的任务都终止
print('Epoch %d, training time = %.1f sec' % (e, time() - start))
correct, num = 0.0, 0.0
for batch in valid_data:
correct += self.valid_batch(batch, ctx, net)
num += batch[0].shape[0]
print('\tvalidation accuracy = %.4f' % (correct / num))
Подробный анализ методов пакетного обученияtrain_batch()
:
- Входной пакет представляет собой набор данных и меток с индексом 0 для данных и индексом 1 для меток.
- В зависимости от количества графических процессоров, разделенных данных данных и меток меток каждый графический процессор соответствует разным данным;
- Для каждой группы данных и меток обратное распространение назад() соответственно обновляет параметры сети сети;
- Установите шаг тренера трейнера как количество партий
batch_size
;
Несколько графических процессоров не зависят друг от друга, поэтому при использовании нескольких графических процессоров для обучения моделей необходимо обращать внимание на слияние данных между разными графическими процессорами.
Реализация выглядит следующим образом:
@staticmethod
def train_batch(batch, ctx, net, trainer):
# split the data batch and load them on GPUs
data = gluon.utils.split_and_load(batch[0], ctx) # 列表
label = gluon.utils.split_and_load(batch[1], ctx) # 列表
# compute gradient
GluonFirst.forward_backward(net, data, label)
# update parameters
trainer.step(batch[0].shape[0])
@staticmethod
def forward_backward(net, data, label):
loss = gluon.loss.SoftmaxCrossEntropyLoss()
with autograd.record():
losses = [loss(net(X), Y) for X, Y in zip(data, label)] # loss列表
for l in losses: # 每个loss反向传播
l.backward()
Метод проверки конкретной аналитической партииvalid_batch()
:
- Запустите все данные проверки в одном графическом процессоре, а именно в ctx[0];
- Сетевая сеть прогнозирует вероятность категории данных данных, а затем преобразует ее в определенную категорию argmax();
- Объедините все правильно предсказанные выборки, чтобы получить общее количество правильных выборок;
Реализация выглядит следующим образом:
@staticmethod
def valid_batch(batch, ctx, net):
data = batch[0].as_in_context(ctx[0])
pred = nd.argmax(net(data), axis=1)
return nd.sum(pred == batch[1].as_in_context(ctx[0])).asscalar()
За исключением обучающей части, загрузка данных графического процессора и сетевая модель согласуются с центральным процессором.
Чтобы обучить модель графического процессора, вам необходимо подключиться к удаленному серверу и загрузить проект. Рекомендуется, если транспорт Git недоступенRsyncOSX, очень удобный инструмент синхронизации файлов:
На удаленном сервере установите библиотеку зависимостей проекта в виртуальную среду, обратите внимание, что вам нужно использовать версию MXNet для графического процессора.mxnet-cu80
, а затем выполните обучение модели.
Вот вывод модели для версии GPU:
Epoch 5, training time = 13.7 sec
validation accuracy = 0.9277
Epoch 6, training time = 13.9 sec
validation accuracy = 0.9284
Epoch 7, training time = 13.8 sec
validation accuracy = 0.9335
Epoch 8, training time = 13.7 sec
validation accuracy = 0.9379
Epoch 9, training time = 14.4 sec
validation accuracy = 0.9402
При появлении следующего предупреждения ⚠️:
only 4 out of 12 GPU pairs are enabled direct access.
It may affect the performance. You can set MXNET_ENABLE_GPU_P2P=0 to turn it off
закрытиеMXNET_ENABLE_GPU_P2P
То есть на нормальный тренировочный процесс это никак не влияет.
export MXNET_ENABLE_GPU_P2P=0
ужеMXNet/GluonЗавершен инженерный проект MXNet. Детали реализации MXNet анализируются по четырем частям набора данных, модели, обучения и графического процессора. Каждая ссылка MXNet очень продумана, похожа на другие структуры и проста в использовании. Хотя пример небольшой, он «укомплектован пятью внутренними органами» и играет роль привлечения других к продолжению изучения фреймворка MXNet.
OK, that's all! Enjoy it!