Примеры
Первый шаг обучения #
Построим небольшую сеть на CPU, вычислим градиенты и сохраним состояние. Это проверка вычислительного пути на синтетических данных, без выводов о качестве обучения или преимуществах топологии.
Модель, ошибка и оптимизатор #
Установите PyTorch по инструкции быстрого старта. Следующий блок можно выполнить целиком:
import torch
from regnets.kernels import MLP
from regnets.modular import Layer, ModularNet
from regnets.topology.lib import cooley_tukey
torch.manual_seed(7)
topology = cooley_tukey((2, 2, 2, 2))
description = Layer(
kernel=MLP(hidden=(16,)),
shared=False,
residual=True,
in_size=3,
)
net = ModularNet(topology, description, device="cpu")
optimizer = torch.optim.SGD(net.parameters(), lr=0.01)
x = torch.randn(4, 16, 3)
target = torch.zeros_like(x)
net.train()
optimizer.zero_grad(set_to_none=True)
prediction = net(x)
assert prediction.shape == target.shape
loss = (prediction - target).square().mean()
loss.backward()
assert all(p.grad is not None for p in net.parameters())
optimizer.step()
net.eval()
with torch.no_grad():
result = net(x)
assert torch.isfinite(result).all()
Все слои получают одно описание, но создают собственные параметры.
shared=False задаёт независимые параметры позициям модулей внутри каждого
слоя. При shared=True позиции слоя используют одни параметры;
разные слои сохраняют независимые веса в обоих случаях.
residual=True добавляет обход одного ядра и требует совпадающих p[m],
g[m] и размеров вектора. При изменении этих размеров используйте
Residual(project=True); параметры описаны в
справке по модели.
Сохранение и проверка восстановления #
Продолжите пример теми же net, topology, description и x:
torch.save(net.state_dict(), "weights.pt")
restored = ModularNet(topology, description, device="cpu")
state = torch.load("weights.pt", map_location="cpu", weights_only=True)
restored.load_state_dict(state)
restored.eval()
with torch.no_grad():
torch.testing.assert_close(restored(x), net(x))
Словарь состояния содержит параметры и _extra_state с описанием
топологии и слоёв. Несовместимая конфигурация вызывает RuntimeError.
Производные индексы восстанавливаются конструктором.
Создание модели остаётся обязанностью вызывающего кода. Сохраняйте рядом
с весами код конфигурации, версию Regnets и параметры эксперимента.
Состояние оптимизатора, номер шага, состояние генераторов случайных чисел
и набор данных нужны отдельно, если вы собираетесь продолжать обучение.
JSON топологии и state_dict решают разные задачи.
Изменение формы контактов #
Число контактов определяет топология, длину вектора — Layer:
| Режим | Вход сети | Выход сети |
|---|---|---|
| Скалярный | [..., net.n_inputs] |
[..., net.n_outputs] |
| Векторный | [..., net.n_inputs, in_size] |
[..., net.n_outputs, out_size] |
Здесь in_size относится к первому Layer, out_size — к последнему.
Пропущенный out_size равен in_size. Для переходов между размерами передайте
по одному совместимому Layer на слой. Не смешивайте скалярный и векторный
режимы; даже in_size=1 требует отдельной оси вектора.
См. также справочник модели и справочник ядер.
Собственное нейронное ядро #
Наследуйте regnets.kernels.Kernel и реализуйте build(shape).
Метод вызывается при создании сети и возвращает новый torch.nn.Module.
Все обучаемые параметры должны быть зарегистрированы до создания оптимизатора.
Контракт формы и независимости #
KernelShape передаёт in_features, out_features, positions, shared,
device, dtype. Ядро принимает [..., positions, in_features] и возвращает
[..., positions, out_features] с теми же ведущими измерениями.
Оно может смешивать локальные признаки, сохраняя независимость позиций и
объектов пакета. При shared=False независимость параметров реализует автор ядра.
Пример: обучаемый локальный масштаб #
Этот блок сохраняет число признаков. В общем режиме у него один вектор весов, в независимом — отдельный вектор у каждой позиции:
from dataclasses import dataclass
import torch
from torch import nn
from regnets.kernels import Kernel, KernelShape
from regnets.modular import Layer, ModularNet
from regnets.topology.lib import cooley_tukey
class _ScaleModule(nn.Module):
def __init__(self, shape: KernelShape):
super().__init__()
dimensions = (shape.in_features,) if shape.shared else (
shape.positions, shape.in_features
)
self.weight = nn.Parameter(
torch.ones(dimensions, device=shape.device, dtype=shape.dtype)
)
def forward(self, x):
return x * self.weight
@dataclass(frozen=True)
class LocalScale(Kernel):
def output_features(self, in_features: int, default: int) -> int:
return in_features
def build(self, shape: KernelShape) -> nn.Module:
if shape.in_features != shape.out_features:
raise ValueError("LocalScale preserves its feature count.")
return _ScaleModule(shape)
net = ModularNet(
cooley_tukey((2, 2)),
Layer(kernel=LocalScale(), shared=False, in_size=3),
device="cpu",
)
x = torch.randn(2, 4, 3)
y = net(x)
assert y.shape == x.shape
y.square().mean().backward()
assert all(p.grad is not None for p in net.parameters())
output_features определяет промежуточную ширину внутри Sequential.
У блоков, сохраняющих ширину, он возвращает in_features. В build
проверяется совместимость с требуемым выходом слоя.
Что проверять в собственном ядре #
- Форму результата при одиночном примере и нескольких пакетных измерениях.
- Независимость позиций и соблюдение
shared. - Регистрацию параметров и прохождение градиентов.
device,dtype, режимыtrain()иeval(), сохранение и загрузку состояния.
ModularNet проверяет форму результата, но автоматически не преобразует
произвольный nn.Module в векторизованное ядро. Полный контракт доступен
в справочнике Kernel и KernelShape.
Рисунок топологии из JSON #
Модуль regnets.topology.viz входит в пакет и сохраняет полную топологию в SVG
или PNG. Он использует Matplotlib, уже входящий в зависимости проекта.
Для работы нужны только установленный пакет и входной файл: Web App,
браузер, графическая среда и PyTorch в процесс не загружаются.
Python #
from regnets.topology.viz import render_topology
render_topology("topology.json") # topology.svg рядом с JSON
render_topology("topology.json", "modules.svg", mode="modules")
render_topology("topology.json", "contacts.png", dpi=200)
Функция возвращает pathlib.Path созданного файла. Формат определяется
расширением результата, регистр расширения несущественен. Если выходной путь
не задан, расширение исходного файла заменяется на .svg.
Недостающие каталоги результата создаются автоматически; существующий
рисунок перезаписывается. Исходный JSON не перезаписывается.
| Параметр | По умолчанию | Назначение |
|---|---|---|
source |
обязателен | Путь к JSON с полным описанием топологии |
output |
рядом с JSON, .svg |
Путь к SVG или PNG |
mode |
"contacts" |
"contacts" — контакты и связи внутри ядер; "modules" — модули и межслойные связи |
dpi |
300 |
Разрешение PNG, положительное целое число; на векторную геометрию SVG не влияет |
Режимы совпадают по смыслу и маршрутам связей с Web App и используют общий
модуль regnets.topology.graph. Сеть выводится целиком. В режиме модулей бирюзовые
точки отмечают входы, терракотовые — выходы; центры точек лежат на рамке.
Фиолетовая рамка отличается от синих линий связи.
SVG остаётся векторным, текст сохраняется текстом в шрифте DejaVu Sans.
Над графом указаны имя (если задано), основания p и g, предложение из
слов фактически построенной топологии и названия слоёв. Длинные строки
уменьшаются по размеру, чтобы поместиться в ширину рисунка.
Для больших сетей высота рисунка автоматически увеличивается, чтобы подписи
контактов не накладывались друг на друга.
Командная строка #
После uv sync, из корня проекта:
uv run python tools/render_topology.py topology.json
uv run python tools/render_topology.py topology.json -m modules -o network.png
uv run python tools/render_topology.py topology.json -o network.png --dpi 200
uv run python tools/render_topology.py --help
Короткие ключи -o и -m имеют полные варианты --output и --mode.
У утилиты командной строки значение --dpi по умолчанию равно 150;
у функции Python render_topology — 300.
Утилита печатает путь созданного рисунка. При ошибке файла или параметров
печатает сообщение в stderr и завершается с кодом 2.
Готовый пример на 16 входов — examples/topology.json. Сохранить его в отдельный каталог:
uv run python tools/render_topology.py examples/topology.json -o build/topology.svg
uv run python tools/render_topology.py examples/topology.json -m modules -o build/modules.png
JSON и ограничения #
Формат, состав слов и правила двойственности заданы в
документе дизайна.
Поддерживаются стандартные и произвольные схемы, разные p/g и dual.
Преобразование двойственности применяется ровно один раз после чтения файла.
Общее чтение доступно также отдельно:
from regnets.topology.io import load_topology
spec = load_topology("topology.json")
indices = spec.topology.permutations()
load_topology проверяет структуру JSON независимо от ограничений Web UI:
размерность модуля может превышать 16, число слоёв — 12. p и g
содержат ровно по одному положительному целому числу на слой и хранятся
в spec.topology.
spec.to_dict() возвращает каноническую запись с исходными словами,
исходными размерностями и флагом двойственности.
Построение рисунка ограничено 60000 элементами графа; проверка выполняется
до выделения контактов и связей. Для PNG дополнительно допускается не более
40 миллионов пикселей и 65535 пикселей по каждой стороне. При превышении
выдаётся ошибка: граф никогда не усекается. Для больших сетей предпочтителен
SVG; для PNG можно уменьшить dpi.
Функция сообщает ошибки данных через ValueError, чтения/записи — через
OSError. Все вычисления и вывод рисунка выполняются на CPU.
Работа с визуализатором #
Откройте визуализатор, чтобы исследовать связи без установки библиотеки. Топология рассчитывается в браузере; веса и обучение здесь не вычисляются.
Постройте первую схему #
- Выберите стандартную схему и число слоёв.
- Введите
p— число входов каждого модуля,g— число выходов. Одно число применяется ко всем слоям; список содержит по числу на слой. Пустое полеgозначаетg=p. - При необходимости задайте свободное название.
- Нажмите «Построить граф». При ошибке ввода последняя схема сохраняется.
Кнопки «16», «64» и «256» сразу применяют пример с модулями 2 × 2. Переключатель двойственности также применяет изменение сразу. Параметры и редактор слов описывают исходную модель, граф показывает выбранную модель.
Прочитайте связи #
В режиме «Контакты» точки обозначают контакты, линии внутри слоя — связи входов и выходов одного ядра. В режиме «Модули» прямоугольник обозначает ядро, линия — передачу значения между ядрами. Бирюзовые точки слева — входы, терракотовые справа — выходы.
Нажмите контакт, модуль или связь: инспектор покажет свойства выбранного
элемента. Подпись модуля имеет вид слой, номер в слое.
Колесо меняет масштаб, перетаскивание перемещает схему, «Вписать» возвращает текущий диапазон целиком. Для перехода с клавиатуры выберите поле или слой, введите номер в строке «Найти» и нажмите «Перейти».
Изучите часть большой сети #
Первоначально показана вся сеть. Поля «Слои» задают включительный диапазон; кнопка «Все слои» снимает это ограничение. Таблица слов продолжает показывать всю топологию.
Приложение допускает 1–12 слоёв и размерности модулей 1–16. Перед построением оно подсчитывает связи входов с выходами внутри всех ядер топологии. Если их больше 2²⁰ (1 048 576), граф не строится, а приложение предлагает сохранить конфигурацию в JSON. Проверка учитывает всю топологию независимо от режима и выбранных слоёв. Граф не усекается автоматически.
Ограничения визуализатора не распространяются на программное создание
объектов Topology и формат JSON.
Свои слова и обмен файлами #
Выберите «Своя топология», раскройте «Числовые слова» и введите список списков JSON. Размеры списков и допустимые коды проверяются по контракту JSON.
- Открыть JSON — загрузить полное описание до 128 КБ, включая
p,g, имя иdual. - Сохранить JSON — сохранить полную исходную модель и выбор двойственности.
- Скачать слова TXT — получить числовые слова выбранной модели; без
p/gэто неполное описание. - Скачать PNG — сохранить рисунок текущего вида графа.
Полный SVG или PNG из Python можно получить по руководству экспорта. Канонический формат обмена описан в JSON v1.
Для локального серверного приложения Dash существует отдельное руководство.