← На главную
Гайды· 11.06.2026· 4 мин чтения

Квантовый слой вместо матричного умножения: строим гибридную нейросеть на CUDA-Q

Как встроить квантовый вычислитель на базе теории Orch-OR в кортикально-спайковую нейросеть с помощью NVIDIA CUDA-Q 0.12. Пошаговый гайд с кодом.

Квантовый слой вместо матричного умножения: строим гибридную нейросеть на CUDA-Q
Материал подготовлен с помощью ИИ и проверен редактором

Матричное умножение — это не мышление. Если вы строите нейросеть, которая должна имитировать работу коры мозга, рано или поздно упрётесь в этот факт. Гайд показывает, как добавить квантовый Readout-слой в кортикально-спайковую сеть — с реальным кодом, без криостата и без QPU.


Зачем вообще квантовый слой в нейросети

Стандартная нейросеть — детерминированная машина. Подали вход, получили выход, никаких сюрпризов. Мозг работает иначе: он не вычисляет ответ, он сужает пространство возможностей до одного события. Именно эту идею описывает теория Orchestrated Objective Reduction (Orch-OR), которую в 1990-х предложили физик Роджер Пенроуз и анестезиолог Стюарт Хамерофф.

Суть теории: внутри нейронов есть микротрубочки из белка тубулина. Пенроуз предположил, что тубулин образует квантовые суперпозиции, которые коллапсируют не из-за наблюдателя, а сами по себе — под действием гравитации, за конечное время. Хамерофф добавил: именно этот механизм «собирает» сознание, а анестетики выключают его, разрушая квантовую когерентность тубулина. Теория спорная, но она даёт конкретную архитектурную идею — квантовый коллапс как финальный шаг вычисления.

Мы реализуем это в виде квантового Readout-слоя поверх кортикально-спайковой сети. Во всём мире опубликовано не больше пяти подобных работ — хороший повод разобраться самому.


Что понадобится

Железо и окружение:

  • GPU NVIDIA архитектуры Turing, Ampere, Ada, Hopper или Blackwell (RTX 20xx и новее)
  • ~24 ГБ оперативной памяти на одну эпоху обучения (сеть учится одновременно на GPU и CPU с квантовой симуляцией)
  • Python 3.10+

Установка зависимостей:

``bash pip install cudaq torch networkx numpy ``

В гайде используется CUDA-Q версии 0.12. Код совместим с соседними версиями, но проверялся именно на 0.12.

CUDA-Q (NVIDIA CudaQ) — открытая платформа для гибридных квантово-классических приложений. Она объединяет GPU, CPU и QPU в едином рабочем процессе. QPU у нас нет, поэтому переключаем платформу в режим симуляции на видеокарте.


Структура файла и базовые импорты

Создаём файл brain_quantum.py:

```python #!/usr/bin/env python3 import gc import torch from torch import nn import torch.nn.functional as F import networkx as nx import math import numpy as np import cudaq

Симулируем QPU на GPU

cudaq.set_target("nvidia") ```

cudaq.set_target("nvidia") — ключевая строка. Без неё CUDA-Q попытается найти реальный квантовый процессор и упадёт с ошибкой.


Как устроено квантовое ядро

Квантовое ядро — минимальная схема, которая превращает обычный вектор чисел в квантовое состояние. Не в результат измерения и не в битовую строку, а именно в состояние: волну вероятностей, которая ещё не сделала выбор.

Регистр из n_qubits кубитов (в нашем случае 10) стартует в базовом состоянии:

`` |0000000000⟩ ``

Это нулевая конфигурация — никакой информации, никакой памяти. Данные вводятся не записью числа в ячейку, а поворотом состояния кубита на сфере Блоха с помощью гейта RY(θ):

``python @cudaq.kernel def orch_or_kernel(angles: list[float]): qubits = cudaq.qvector(10) # n_qubits = 10 # Кодируем входной вектор как повороты на сфере Блоха for i in range(10): ry(angles[i], qubits[i]) # Запутываем соседние кубиты (имитация некласической корреляции) for i in range(9): cx(qubits[i], qubits[i + 1]) ``

RY(θ) — вращение вокруг оси Y. Каждый угол angles[i] становится не числом в памяти, а физическим преобразованием состояния. В результате каждый кубит перестаёт быть строго 0 или 1: входной вектор превращается в «вектор возможностей».

После поворотов кубиты независимы — каждый в своей суперпозиции. Чтобы получить нечто похожее на нейронную корреляцию, нужно их запутать. Гейт CX (CNOT) создаёт некласическую зависимость между соседними кубитами — аналог того, как микротрубочки в дендрите передают состояние вдоль отростка.


Встраиваем квантовый слой в PyTorch

Квантовое ядро само по себе не обучается — у него нет градиентов. Чтобы встроить его в обучаемую сеть, оборачиваем вызов CUDA-Q в torch.autograd.Function с ручным вычислением градиента через конечные разности (parameter-shift rule):

```python class OrchORFunction(torch.autograd.Function): @staticmethod def forward(ctx, angles): angles_list = angles.detach().cpu().tolist() result = cudaq.observe( orch_or_kernel, cudaq.SpinOperator.from_word("Z" * 10), angles_list ).expectation() ctx.save_for_backward(angles) return torch.tensor([result], dtype=torch.float32)

@staticmethod def backward(ctx, grad_output): (angles,) = ctx.saved_tensors grads = torch.zeros_like(angles) shift = math.pi / 2 for i in range(len(angles)): angles_plus = angles.clone() angles_plus[i] += shift angles_minus = angles.clone() angles_minus[i] -= shift e_plus = cudaq.observe( orch_or_kernel, cudaq.SpinOperator.from_word("Z" 10), angles_plus.tolist() ).expectation() e_minus = cudaq.observe( orch_or_kernel, cudaq.SpinOperator.from_word("Z" 10), angles_minus.tolist() ).expectation() grads[i] = (e_plus - e_minus) / 2.0 return grad_output * grads ```

cudaq.observe вычисляет математическое ожидание оператора (здесь — произведение операторов Паули Z по всем кубитам). Это и есть «результат измерения» — одно число, в которое схлопывается вся квантовая суперпозиция. Orch-OR в действии.


Где ломается

Память. 24 ГБ RAM — это минимум для одной эпохи. Квантовая симуляция 10 кубитов хранит вектор состояния размером 2^10 = 1024 комплексных числа, но накладные расходы CUDA-Q на GPU значительно больше. При увеличении n_qubits до 20 потребуется уже ~1 ГБ только на вектор состояния.

Скорость. Parameter-shift rule требует двух прогонов квантового ядра на каждый параметр. При 10 кубитах это 20 вызовов cudaq.observe на один backward pass. Батч из 32 примеров — уже 640 вызовов. Обучение медленное.

Градиенты. cudaq.observe возвращает Python float, а не тензор с историей вычислений. Если забыть обернуть вызов в autograd.Function, градиенты просто не дойдут до классической части сети.

Версионная совместимость. CUDA-Q 0.12 и PyTorch 2.x требуют совпадения версий CUDA. Проверьте nvcc --version и torch.version.cuda перед установкой.


Что попробовать дальше

  • Увеличить n_qubits до 12-16 и сравнить качество классификации с классическим линейным Readout-слоем того же размера.
  • Заменить SpinOperator.from_word("Z" * 10) на обучаемый гамильтониан — тогда сама «наблюдаемая величина» станет параметром сети.
  • Попробовать cudaq.set_target("qpp-cpu") для воспроизводимости на машинах без NVIDIA GPU (медленнее, но не требует видеокарты).
  • Следить за проектом CUDA-Q на GitHub: в версиях после 0.12 появляется нативная поддержка градиентов через adjoint-метод, что уберёт необходимость в ручном parameter-shift.

Источники

Автор: PLai AI