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

Mutations

4.2 Операторы мутации

Оператор Тип Описание Математика
split Структурная Вставка скрытой вершины Ребро \(u \to w\) disable; создаются \(u \to n \to w\); \(\mathbf{s}(n) = \lfloor(\mathbf{s}(u)+\mathbf{s}(w))/2\rfloor\)
without_split Структурная Добавление параллельного ребра Новое \((u,w)\) при сохранении DAG + constraints
mutate_weights Весовая Гауссов шум на \(\sigma\) \(\sigma \leftarrow \text{clip}(\sigma + \varepsilon, [\sigma_\min, \sigma_\max])\), \(\varepsilon \sim \mathcal{N}(0, \tau^2)\), \(\tau = 0.5\); rate=0.8; с prob 0.1 — полный resample
aggressive_mutate_weights Весовая Агрессивная мутация \(\sigma\) rate=1.0, scale=1.5
remove_edge Структурная Удаление/disable одного ребра Связность input→output; кандидат из list_removable_edges
remove_edges Структурная Удаление до REMOVE_EDGES_COUNT=3 non-bridge рёбер Пересчёт removable после каждого удаления; кандидаты — не-мосты
remove_node Структурная Удаление скрытого узла Удаляются все инцидентные рёбра; rebuild
dissolve_node Структурная Контракция скрытого узла dissolve_hidden_node: узел стягивается, предшественники перекоммутируются на потомков (связность сохраняется); кандидаты из list_dissolvable_hidden_nodes
crossover Рекомбинация Скрещивание двух родителей Union включённых рёбер (см. §4.3)
mutate_activation Структурная (opt-in) Смена σ ровно у одной не-входной вершины Кандидаты (node_id, new_act) из пула; веса / рёбра / каналы не трогать. Нет в DEFAULT_MUTATION_TYPES — только при evolve_node_activations=True

Выбор оператора — из легального множества (кандидаты), не слепой retry.

Clamp весов: \(\sigma \in [\text{WEIGHT\_CLAMP\_MIN}, \text{WEIGHT\_CLAMP\_MAX}] = [-8, 8]\).

Полная мутация \(\sigma\):

\[ \sigma' = \begin{cases} \mathcal{U}(-2, 2) & \text{с вероятностью } 0.1 \text{ (full reset)} \\ \text{clip}(\sigma + \mathcal{N}(0, \tau^2),\; [\sigma_\min, \sigma_\max]) & \text{с вероятностью } 0.9 \cdot \text{rate} \end{cases} \]

Для каждого elite-родителя порождаются потомки всеми типами мутаций из MUTATION_TYPES, плюс агрессивный клон (without_split × 5).

Script 06 vs 07

Скрипт 06 (OVA) на старте убирает remove_edge / remove_edges из набора, скрипт 07 их сохраняет (config.py, комментарий у MUTATION_TYPES).

Мутации

Сначала кандидаты, затем один оператор.

4.2.1 Батч-предложение и параллельные мутации

Для крупных популяций перечисление кандидатов и применение операторов выносится из горячего цикла:

  • propose_batch (mutations.py) — один раз перечислить легальные множества для всех родителей, затем последовательно применить операторы (без повторного скана кандидатов на каждого потомка).
  • mutation_mp.propose_parents_mp (cnn_neat/mutation_mp.py) — ProcessPool по родителям (обход GIL). В production используется topology-only payload (~КиБ на потомка): воркеры мутируют «безвесовых» родителей, а evolver.py затем переприкрепляет conv-веса родителя к вернувшимся детям. Число процессов — runtime_cpu.resolve_cpu_workers(mutation_propose_parallel) (0 = все CPU). При BrokenProcessPool — откат на последовательный путь.

Управление: ExperimentConfig.mutation_propose_parallel (0 = авто), mutation_propose_max_children. Cone-размножение (breeding_cone_mp) использует тот же пул и сериализацию генома (genome_to_payload / genome_from_payload).