Исполнение нейронной сети, созданной из проекций и популяций

26 декабря 2025

ID 245069

Этот раздел содержит инструкции по созданию нейронной сети из проекций и популяций, загрузке проекций и популяций на бэкенд для CPU и исполнению нейронной сети.

Этот вариант построения и исполнения нейронной сети используется редко.
Вы можете использовать эту инструкцию при разработке прикладных решений.

Чтобы создать нейронную сеть вручную и исполнить ее:

  1. В директории вашего проекта создайте файл программы формата CPP, в котором будет реализована функция для создания и запуска нейронной сети.
  2. В файле программы подключите заголовочные файлы, необходимые для исполнения нейронной сети, с помощью директивы #include.

    Если требуется, определите псевдонимы с помощью оператора using.

    Пример подключения заголовочных файлов для исполнения нейронной сети с популяцией BLIFAT-нейронов и проекцией дельта-синапсов на однопоточном бэкенде для CPU:

    C++

    #include <knp/backends/cpu-single-threaded/backend.h>

    #include <knp/core/population.h>

    #include <knp/core/projection.h>

    #include <knp/neuron-traits/blifat.h>

    #include <knp/synapse-traits/delta.h>

    #include <vector>

    using Backend = knp::backends::single_threaded_cpu::SingleThreadedCPUBackend;

    using DeltaProjection = knp::core::Projection<knp::synapse_traits::DeltaSynapse>;

    using BLIFATPopulation = knp::core::Population<knp::neuron_traits::BLIFATNeuron>;

    using Population = knp::backends::single_threaded_cpu::SingleThreadedCPUBackend::PopulationVariants;

    using Projection = knp::backends::single_threaded_cpu::SingleThreadedCPUBackend::ProjectionVariants;

  3. Реализуйте генератор нейронов с нужными вам свойствами или используйте готовый генератор из библиотеки фреймворка.

    Пример реализации генератора BLIFAT-нейронов:

    C++

    // ...

    // Реализация функции, генерирующей нейроны.

    // Функция хранится в переменной neuron_generator.

    auto neuron_generator = [](size_t index)

    {

    return knp::neuron_traits::neuron_parameters<knp::neuron_traits::BLIFATNeuron>{};

    };

    // ...

  4. Реализуйте генератор синапсов с нужными вам свойствами или используйте готовый генератор из библиотеки фреймворка.

    Пример реализации генератора дельта-синапсов:

    C++

    // ...

    // Реализация функции, генерирующей синапсы для проекции, которая будет связана

    // с каналом ввода. Функция хранится в переменной input_projection_gen.

    DeltaProjection::SynapseGenerator input_projection_gen = [](size_t index) -> std::optional<DeltaProjection::Synapse>

    {

    return DeltaProjection::Synapse{{1.0, 1, knp::synapse_traits::OutputType::EXCITATORY}, 0, 0};

    };

    // Реализация функции, генерирующей синапсы для проекции, которая будет замыкать

    // вывод популяции на себя. Функция хранится в переменной synapse_generator.

    DeltaProjection::SynapseGenerator synapse_generator = [](size_t index) -> std::optional<DeltaProjection::Synapse>

    {

    return DeltaProjection::Synapse{{1.0, 6, knp::synapse_traits::OutputType::EXCITATORY}, 0, 0};

    };

    // ...

  5. Создайте объект популяции Population и передайте в конструктор созданный генератор нейронов.

    Пример создания объекта популяции:

    C++

    // ...

    // Создание объекта популяции.

    BLIFATPopulation population{neuron_generator, 1};

  6. Создайте объект проекции Projection, которая будет замыкать вывод популяции на себя. Передайте в конструктор идентификатор UID связанной популяции Population и генератор синапсов.

    Пример создания проекции, замыкающей вывод популяции на себя:

    C++

    // ...

    // Создание объекта проекции, замыкающей вывод популяции на себя.

    Projection loop_projection = DeltaProjection{

    population.get_uid(), population.get_uid(), synapse_generator, 1

    };

    // ...

  7. Создайте объект входной проекции Projection. Передайте в конструктор генератор синапсов и идентификатор UID связанной популяции.

    Пример создания входной проекции, связанной с каналом ввода и популяцией:

    C++

    // ...

    // Создание объекта входной проекции, которой присваивается нулевой идентификатор

    // (knp::core::UID{false}). Проекция принимает спайки от канала ввода и отправляет

    // синаптическое воздействие в объект популяции.

    Projection input_projection = DeltaProjection{

    knp::core::UID{false}, population.get_uid(), input_projection_gen, 1

    };

    // Получение UID входной проекции, которая отправляет популяции синаптическое воздействие.

    knp::core::UID input_uid = std::visit([](const auto &proj) { return proj.get_uid(); }, input_projection);

    // ...

  8. Загрузите популяцию и проекции на бэкенд Backend.

    Пример загрузки популяции и проекций на бэкенд:

    C++

    // ...

    Backend backend;

    // ...

    // Загрузка на бэкенд созданного объекта популяции.

    backend.load_populations({population});

    // Загрузка на бэкенд созданных объектов проекций.

    backend.load_projections({input_projection, loop_projection});

  9. Определите объект точки подключения MessageEndpoint к шине сообщений.

    Пример создания точки подключения к шине сообщений:

    C++

    // ...

    // Создание точки подключения к шине сообщений.

    auto endpoint = backend.message_bus_.create_endpoint();

    // ...

  10. Подключите канал ввода InputChannel к входной проекции Projection, а также популяцию Population к каналу вывода OutputChannel. Задайте для каналов ввода и вывода уникальные идентификаторы и сформируйте для них сообщения.

    Пример подключения к каналам ввода и вывода:

    C++

    // ...

    // Создание произвольного UID канала ввода.

    knp::core::UID in_channel_uid;

    // Создание произвольного UID канала вывода.

    knp::core::UID out_channel_uid;

    // Создание подписки на спайки от канала ввода.

    backend.subscribe<knp::core::messaging::SpikeMessage>(input_uid, {in_channel_uid});

    // Создание подписки на спайки от популяции с заданным UID для канала вывода

    // с заданным UID.

    endpoint.subscribe<knp::core::messaging::SpikeMessage>(out_channel_uid, {population.get_uid()});

    ...

  11. Настройте передачу сообщений в нейронной сети и укажите параметры исполнения такта нейронной сети.

    Следующий пример исполнения нейронной сети состоит из 20 шагов:

    C++

    // ...

    std::vector<size_t> results;

    for (size_t step = 0; step < 20; ++step)

    {

    // Отправка спайков входной проекции от канала ввода на шагах 0, 5, 10 и 15.

    if (step % 5 == 0)

    {

    knp::core::messaging::SpikeMessage message{{in_channel_uid, 0}, {0}};

    endpoint.send_message(message);

    }

    backend.step();

    endpoint.receive_all_messages();

    // Получение спайков, отправленных популяцией на канал вывода.

    auto output = endpoint.unload_messages<knp::core::messaging::SpikeMessage>(out_channel_uid);

    // Запись индексов шагов, на которых на канал вывода приходят спайки.

    if (!output.empty()) results.push_back(step);

    }

    // ...

    Шаги исполнения нейронной сети

  12. Сохраните созданный файл.

Если требуется, соберите прикладное решение с помощью CMake.

Вам помогла эта статья?
Что нам нужно улучшить?
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!