Исполнение нейронной сети, созданной из проекций и популяций
Этот раздел содержит инструкции по созданию нейронной сети из проекций и популяций, загрузке проекций и популяций на бэкенд для CPU и исполнению нейронной сети.
Этот вариант построения и исполнения нейронной сети используется редко.
Вы можете использовать эту инструкцию при разработке прикладных решений.
Чтобы создать нейронную сеть вручную и исполнить ее:
- В директории вашего проекта создайте файл программы формата
CPP, в котором будет реализована функция для создания и запуска нейронной сети. - В файле программы подключите заголовочные файлы, необходимые для исполнения нейронной сети, с помощью директивы
#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;
- Реализуйте генератор нейронов с нужными вам свойствами или используйте готовый генератор из библиотеки фреймворка.
Пример реализации генератора BLIFAT-нейронов:
C++
// ...
// Реализация функции, генерирующей нейроны.
// Функция хранится в переменной neuron_generator.
auto neuron_generator = [](size_t index)
{
return knp::neuron_traits::neuron_parameters<knp::neuron_traits::BLIFATNeuron>{};
};
// ...
- Реализуйте генератор синапсов с нужными вам свойствами или используйте готовый генератор из библиотеки фреймворка.
Пример реализации генератора дельта-синапсов:
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};
};
// ...
- Создайте объект популяции
Populationи передайте в конструктор созданный генератор нейронов.Пример создания объекта популяции:
C++
// ...
// Создание объекта популяции.
BLIFATPopulation population{neuron_generator, 1};
- Создайте объект проекции
Projection, которая будет замыкать вывод популяции на себя. Передайте в конструктор идентификаторUIDсвязанной популяцииPopulationи генератор синапсов.Пример создания проекции, замыкающей вывод популяции на себя:
C++
// ...
// Создание объекта проекции, замыкающей вывод популяции на себя.
Projection loop_projection = DeltaProjection{
population.get_uid(), population.get_uid(), synapse_generator, 1
};
// ...
- Создайте объект входной проекции
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);
// ...
- Загрузите популяцию и проекции на бэкенд
Backend.Пример загрузки популяции и проекций на бэкенд:
C++
// ...
Backend backend;
// ...
// Загрузка на бэкенд созданного объекта популяции.
backend.load_populations({population});
// Загрузка на бэкенд созданных объектов проекций.
backend.load_projections({input_projection, loop_projection});
- Определите объект точки подключения
MessageEndpointк шине сообщений.Пример создания точки подключения к шине сообщений:
C++
// ...
// Создание точки подключения к шине сообщений.
auto endpoint = backend.message_bus_.create_endpoint();
// ...
- Подключите канал ввода
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()});
...
- Настройте передачу сообщений в нейронной сети и укажите параметры исполнения такта нейронной сети.
Следующий пример исполнения нейронной сети состоит из 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);
}
// ...
- Сохраните созданный файл.
Если требуется, соберите прикладное решение с помощью CMake.