Перейти к содержанию

Слияние чемпионов «один против остальных» в многоклассовое начальное решение

Модуль cnn_neat/ova_merge.py собирает \(K\) независимых бинарных OVA-чемпионов (по одному на класс) в один с несколькими выходами DAG-геном, который затем дообучается эволюцией (multiclass эксперименты, скрипты 13/14/14b/16). Это статическая сборка графа — без конуса размножения и GD.

Идея

Пусть \(G_0, \dots, G_{K-1}\) — геномы-чемпионы (каждый — DAG свёрток с одним output_node). Объединённый геном \(G^\ast\):

flowchart LR
  x["input (shared)"] --> b0["ветвь класса 0"]
  x --> b1["ветвь класса 1"]
  x --> bk["ветвь класса K-1"]
  b0 --> t0["tip 0 = output_nodes[0]"]
  b1 --> t1["tip 1 = output_nodes[1]"]
  bk --> tk["tip K-1"]
  1. Общий вход. Все чемпионы делят один input-узел (требуется num_input_views=1).
  2. Непересекающиеся ветви. Скрытые узлы каждого чемпиона перенумеровываются (mapping), чтобы избежать коллизий ID; бывший output_node становится новым наконечником в output_nodes[class_id].
  3. Веса. Conv-веса и bias копируются как conv_state_snapshot; edge-скаляры сохраняются (edge_w_{src}_{dst}) или инициализируются 1.0; у объединённого генома edge_weights=True.
  4. Активации. node_activations копируются пер-узел из каждого чемпиона; глобальный activation=None (пер-узловая карта — источник истины).
  5. Объединение метаданных. allowed_channels — объединение по чемпионам; allow_variable_channels — логическое ИЛИ; allowed_new_activations — список встреченных активаций.

API

Символ Роль
ChampionSpec(class_id, genome, source) Чемпион + провенанс (фаза, config, gen)
merge_ova_champions(champions, max_hidden_layers=10**9, max_neurons_per_layer=10**9) Сборка (seed, meta)
save_seed_artifact(seed, meta, output_dir) seed_genome.json + seed_weights.pt + seed_meta.json
load_seed_artifact(seed_dir) Загрузка трёх артефактов

meta содержит num_classes, output_nodes, allowed_new_activations, sources (провенанс по классам), edge_weights, лимиты слоёв.

Полученный seed имеет несколько output_nodes и работает через forward_all_outputs(), что и потребляет multiclass head.