Блиц по PuzzleLib¶
Введение¶
PuzzleLib
- это высокоуровневая нейросетевая библиотека, написанная на Python. Библиотека модульная и динамическая, дизайн навеян Torch и Chainer. Поддерживает вычисления на CPU (Intel/AMD) и GPU (NVIDIA/AMD).
PuzzleLib
позволяет:
- быстро и просто строить разнообразные архитектуры нейронных сетей;
- использовать уже реализованные известные нейросетевые архитектуры, такие как
VGG
,ResNet
,Inception
,UNet
и другие; - обучаться и работать и на GPU, и на CPU.
Установка библиотеки и зависимостей¶
Для подробной инструкции по установке библиотеки и зависимостей см. в документации раздел Windows для установки на ОС Windows и Linux для установки на Linux системы.
Если говорить в общем, то PuzzleLib поддерживает:
- NVIDIA GPU (CUDA backend);
- AMD GPU (ROCm backend);
- Intel CPU (mkl-dnn backend);
- AMD CPU (mkl-dnn/numpy backend);
- Эльбрус CPU (частично)(numpy backend).
Функционал¶
Нейронные сети состоят из различных модулей, выполняющих те или иные операции (свёртка, пулинг, батч-нормализация и т.д.). Создавать их в PuzzleLib очень просто:
from PuzzleLib.Modules import Linear, Activation
from PuzzleLib.Modules.Activation import relu
lin1 = Linear(insize=16, outsize=64)
act = Activation(activation=relu)
lin2 = Linear(insize=64, outsize=1)
Но блоки сети должны быть связаны между собой - для этого нужны контейнеры, например, Sequential:
from PuzzleLib.Containers import Sequential
seq = Sequential()
Добавлять новые слои в контейнер можно командой append
:
seq.append(lin1)
seq.append(act)
seq.append(lin2)
Хотя есть и более удобный способ - контейнер Graph. В этом случае нам нужно сначала явно задать зависимость между слоями с помощью метода node
:
from PuzzleLib.Containers import Graph
lin1 = lin1.node()
act = act.node(lin1)
lin2 = lin2.node(act)
graph = Graph(inputs=lin1, outputs=lin2)
Как только мы построили желаемую архитектуру модели, надо подготовить ее к обучению.
Для этого надо выбрать хороший алгоритм обучения, реализованный в блоке Optimizers, например, MomentumSGD. Сначала импортируем его, инициализируем, передадим в него контейнер с нейронной сетью и выставим необходимые параметры.
from PuzzleLib.Optimizers.MomentumSGD import MomentumSGD
optimizer = MomentumSGD()
optimizer.setupOn(graph, useGlobalState=True)
optimizer.learnRate = 0.1
optimizer.momRate = 0.9
Для обучения еще надо определить функцию потерь, которая будет оценивать, насколько сеть ошиблась при классификации входного объекта. Допустим, это Abs:
from PuzzleLib.Cost import Abs
cost = Abs()
Для упрощения жизни пользователя в библиотеке предусмотрены различные обработчики - вспомогательные объекты для обучения, валидации и стандартного вычисления выхода нейросети.
Чтобы запустить процесс обучения, создается тренер:
from PuzzleLib.Handlers import Trainer
trainer = Trainer(graph, cost, optimizer)
А для валидации сети - валидатор:
from PuzzleLib.Handlers import Validator
validator = Validator(graph, cost)
Заметьте, что валидатор не использует оптимизатор, в отличие от тренера.
И наконец, запуск обучения на 15 эпохах:
import numpy as np
data = np.random.randn(10000, 16).astype(np.float32)
labels = np.random.randn(10000, 1).astype(np.float32)
for i in range(15):
trainer.trainFromHost(data[:8000], labels[:8000], macroBatchSize=400, \
onMacroBatchFinish=lambda train: print(f"Train error: {train.cost.getMeanError():.3f}"))
print(f"Epoch:{i+1:02}" f"\t Accuracy: {(1.0 - validator.validateFromHost(data[8000:], \
labels[8000:], macroBatchSize=400)):.3f}")
optimizer.learnRate *= 0.9
Приставка fromHost
означает, что данные, которые мы передаём в метод trainFromHost
, лежат в оперативной памяти CPU, и их сперва нужно загрузить на GPU. Если данные уже лежат на GPU, то можно использовать аналогичный метод train
.
Параметр macroBatchSize
нужен, чтобы указать, какое количество объектов из всей выборки за раз мы загрузим на GPU. Входные данные будут разделены на батчи, которые последоательно будут посылаться в нейронную сеть для обучения.
В параметре onMacroBatchFinish
мы указываем, какую функцию нужно выполнить, когда macroBatch
прошёл через сеть.