Структурные модели самоподобных сетей
Исходный код

Примеры

Первый шаг обучения #

Построим небольшую сеть на CPU, вычислим градиенты и сохраним состояние. Это проверка вычислительного пути на синтетических данных, без выводов о качестве обучения или преимуществах топологии.

Модель, ошибка и оптимизатор #

Установите PyTorch по инструкции быстрого старта. Следующий блок можно выполнить целиком:

python
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:

python
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 независимость параметров реализует автор ядра.

Пример: обучаемый локальный масштаб #

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

python
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 #

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, из корня проекта:

bash
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. Сохранить его в отдельный каталог:

bash
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. Преобразование двойственности применяется ровно один раз после чтения файла.

Общее чтение доступно также отдельно:

python
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.

Работа с визуализатором #

Откройте визуализатор, чтобы исследовать связи без установки библиотеки. Топология рассчитывается в браузере; веса и обучение здесь не вычисляются.

Постройте первую схему #

  1. Выберите стандартную схему и число слоёв.
  2. Введите p — число входов каждого модуля, g — число выходов. Одно число применяется ко всем слоям; список содержит по числу на слой. Пустое поле g означает g=p.
  3. При необходимости задайте свободное название.
  4. Нажмите «Построить граф». При ошибке ввода последняя схема сохраняется.

Кнопки «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 существует отдельное руководство.

Исходники раздела: docs/training.md · docs/custom-kernels.md · docs/topology-viz.md · docs/visualizer.md