Skip to content
47 changes: 22 additions & 25 deletions examples/mnist-client/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
#[[
© 2024 AO Kaspersky Lab
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]
#[[
© 2024 AO Kaspersky Lab

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]

cmake_minimum_required(VERSION 3.25)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(OpenCV)
if (NOT OpenCV_FOUND)
message(WARNING "OpenCV was not found. Skipping MNIST example...")
return()
endif()

include_directories(${OpenCV_INCLUDE_DIRS})

if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.30")
# Suppress Boost warning.
cmake_policy(SET CMP0167 OLD)
Expand All @@ -45,4 +37,9 @@ add_executable(mnist-client
process_data.cpp
)

target_link_libraries(mnist-client PRIVATE KNP::BaseFramework::Core ${OpenCV_LIBS} ${Boost_LIBRARIES})
find_package(PkgConfig REQUIRED)
pkg_check_modules(GRAPHVIZ REQUIRED IMPORTED_TARGET libgvc libcgraph)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Возможно, искать следует без префикса lib?


target_include_directories(mnist-client PRIVATE ${GRAPHVIZ_INCLUDE_DIRS})
target_link_libraries(mnist-client PRIVATE PkgConfig::GRAPHVIZ )
target_link_libraries(mnist-client PRIVATE KNP::BaseFramework::Core ${Boost_LIBRARIES} )
12 changes: 3 additions & 9 deletions examples/mnist-client/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,9 @@ int main(int argc, char **argv)
// https://click.kaspersky.com/?hl=en-US&version=2.0&pid=KNP&link=online_help&helpid=235801
// https://click.kaspersky.com/?hl=en-US&version=2.0&pid=KNP&link=online_help&helpid=274991
knp::framework::Network network = knp::framework::sonata::load_network(network_path);
// Constructs a network graph.
const knp::framework::NetworkGraph net_graph(network);
// Prints descriptions of graph connections.
knp::framework::print_network_description(net_graph);
// Draws a subgraph in the OpenCV window.
// Press `Esc` to exit the OpenCV window.
knp::framework::position_network_test(
knp::framework::NetworkGraph(network), knp::framework::divide_graph_by_connectivity(net_graph)[0],
{1000, 700});

// knp::framework::set_saving_path("temp_test_dir");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Удалить.

knp::framework::visualize_network(network);
}

// If `task=infer`, the function loads a network and runs inference.
Expand Down
25 changes: 0 additions & 25 deletions examples/mnist-client/process_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,13 @@
#include <utility>
#include <vector>

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>


/**
* @brief Filesystem namespace alias.
*/
namespace fs = std::filesystem;


/**
* @brief Visualize data instances.
* @param data vector of flattened images.
* @param size output image size.
*/
cv::Mat draw_data(const std::vector<unsigned char> &data, const cv::Size &size)
{
cv::Mat out_img(size, CV_8UC1);
for (int y = 0; y < size.height; ++y)
{
for (int x = 0; x < size.width; ++x)
{
out_img.at<unsigned char>(cv::Point2i{x, y}) = data[size.width * y + x];
}
}
cv::imshow("Data", out_img);
std::cout << cv::sum(out_img) << std::endl;
cv::waitKey(0);
return out_img;
}


/**
* @brief Turn data frames into spikes.
* @param buf data frame.
Expand Down
7 changes: 6 additions & 1 deletion examples/mnist-learn/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ if (NOT TARGET KNP::BaseFramework::Core)
endif()

find_package(Boost ${KNP_BOOST_MIN_VERSION} COMPONENTS program_options REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GRAPHVIZ REQUIRED IMPORTED_TARGET libgvc libcgraph)

add_executable(${PROJECT_NAME}
main.cpp
Expand All @@ -40,4 +42,7 @@ add_executable(${PROJECT_NAME}
models/altai/prepare_network_for_inference.cpp
models/altai/spike_generators.cpp)
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR})
target_link_libraries(${PROJECT_NAME} PRIVATE KNP::BaseFramework::Core Boost::program_options)
target_link_libraries(${PROJECT_NAME} PRIVATE
KNP::BaseFramework::Core
Boost::program_options
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Скобку наверх.

19 changes: 18 additions & 1 deletion examples/mnist-learn/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,16 @@
* limitations under the License.
*/

#include <knp/framework/io/input_channel.h>
#include <knp/framework/monitoring/observer.h>
#include <knp/framework/network.h>
#include <knp/framework/sonata/network_io.h>
#include <knp/framework/visualizer/visualize_network.h>

#include <iostream>

#include <boost/program_options.hpp>

#include "dataset.h"
#include "evaluate_results.h"
#include "inference.h"
Expand All @@ -31,6 +39,7 @@

/**
* @brief Run whole model.
*
* @tparam Neuron Neuron type.
* @param model_desc Model description.
*/
Expand All @@ -43,10 +52,16 @@ void run_model(const ModelDescription& model_desc)

// Online Help link: https://click.kaspersky.com/?hl=en-US&version=2.0&pid=KNP&link=online_help&helpid=243548
knp::framework::BackendLoader backend_loader;
train_model<Neuron>(model_desc, dataset, network, backend_loader);
auto backend = train_model<Neuron>(model_desc, dataset, network, backend_loader);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вообще странно получать бэк из функции тренировки модели.


if (!model_desc.model_saving_path_.empty()) save_network(model_desc, network);


// knp::framework::set_saving_path("temp_test_dir");
visualize_network(network.network_);
visualize_network(network.network_, backend);
Comment on lines +61 to +62

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я так понимаю, где-то есть какие-то скрытые переменные, и потому вызов делается несколько раз?

Если да, так не должно быть. Всё надо сделать явно.

visualize_bus(network.network_, backend);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вообще непонятно, причём тут шина.


auto inference_spikes = infer_model<Neuron>(model_desc, dataset, network, backend_loader);

evaluate_results(inference_spikes, dataset);
Expand All @@ -55,8 +70,10 @@ void run_model(const ModelDescription& model_desc)

/**
* @brief Main function.
*
* @param argc Argument count.
* @param argv Arguments value.
*
* @return Error code.
*/
int main(int argc, char** argv)
Expand Down
32 changes: 14 additions & 18 deletions examples/mnist-learn/models/blifat/construct_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,19 @@ using ResourceNeuronData = knp::neuron_traits::neuron_parameters<knp::neuron_tra
struct NetworkPopulations
{
/// Input population.
const PopulationInfo &input_pop_;
const PopulationInfo& input_pop_;
/// Output population.
const PopulationInfo &output_pop_;
const PopulationInfo& output_pop_;
/// Gate population. Used for training.
const PopulationInfo &gate_pop_;
const PopulationInfo& gate_pop_;
/// Population for rasterized images.
const PopulationInfo &raster_pop_;
const PopulationInfo& raster_pop_;
/// Population for images labels.
const PopulationInfo &target_pop_;
const PopulationInfo& target_pop_;
};


static NetworkPopulations create_populations(NetworkConstructor &constructor)
static NetworkPopulations create_populations(NetworkConstructor& constructor)
{
// Creating neurons.
// Online Help link: https://click.kaspersky.com/?hl=en-US&version=2.0&pid=KNP&link=online_help&helpid=235859
Expand All @@ -78,25 +78,22 @@ static NetworkPopulations create_populations(NetworkConstructor &constructor)
input_neuron.stochastic_stimulation_ = stochastic_stimulation;

// Creating populations using neurons.
const auto &input_pop =
const auto& input_pop =
constructor.add_population(input_neuron, num_input_neurons, PopulationRole::INPUT, true, "INPUT");
const auto &output_pop =
const auto& output_pop =
constructor.add_population(default_neuron, classes_amount, PopulationRole::OUTPUT, true, "OUTPUT");
const auto &gate_pop =
constructor.add_population(default_neuron, classes_amount, PopulationRole::NORMAL, false, "GATE");
const auto &raster_pop = constructor.add_channeled_population(input_size, true);
const auto &target_pop = constructor.add_channeled_population(classes_amount, false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А это зачем удалять?

const auto& gate_pop =
constructor.add_population(default_neuron, classes_amount, PopulationRole::NORMAL, true, "GATE"); // was false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Комментарий "was false" вводит в заблуждения и не несёт смысловой нагрузки, - лучше убрать или дополнить.

const auto& raster_pop = constructor.add_channeled_population(input_size, true);
const auto& target_pop = constructor.add_channeled_population(classes_amount, true); // was false
// Returning them.
return {input_pop, output_pop, gate_pop, raster_pop, target_pop};
}


static void create_projections(
AnnotatedNetwork &network, NetworkConstructor &constructor, const NetworkPopulations &pops)
AnnotatedNetwork& network, NetworkConstructor& constructor, const NetworkPopulations& pops)
{
// Creating synapse and projection out of it. Multiple times.

// Synapse creation.
ResourceSynapseParams raster_to_input_synapse;
raster_to_input_synapse.rule_.synaptic_resource_ =
Expand Down Expand Up @@ -172,7 +169,7 @@ static void create_projections(
* @see [Online Help](https://click.kaspersky.com/?hl=en-US&version=2.0&pid=KNP&link=online_help&helpid=235801)
*/
template <>
AnnotatedNetwork construct_network<knp::neuron_traits::BLIFATNeuron>(const ModelDescription &model_desc)
AnnotatedNetwork construct_network<knp::neuron_traits::BLIFATNeuron>(const ModelDescription& model_desc)
{
AnnotatedNetwork result;

Expand All @@ -187,7 +184,6 @@ AnnotatedNetwork construct_network<knp::neuron_traits::BLIFATNeuron>(const Model

// Add input_pop as WTA sender.
result.data_.wta_data_.emplace_back().first.push_back(pops.input_pop_.uid_);

create_projections(result, constructor, pops);
}

Expand Down
7 changes: 4 additions & 3 deletions examples/mnist-learn/training.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
#include <knp/framework/projection/wta.h>
#include <knp/framework/tags/name.h>

#include <map>
#include <memory>
#include <filesystem>
#include <fstream>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -162,12 +162,13 @@ void train_network(
* @param backend_loader Backend loader.
*/
template <typename Neuron>
void train_model(
std::shared_ptr<knp::core::Backend> train_model(
const ModelDescription& model_desc, const Dataset& dataset, AnnotatedNetwork& network,
knp::framework::BackendLoader& backend_loader)
{
std::shared_ptr<knp::core::Backend> training_backend = backend_loader.load(model_desc.training_backend_path_);
train_network<Neuron>(training_backend, network, model_desc, dataset);

prepare_network_for_inference<Neuron>(training_backend, model_desc, network);
return training_backend;
}
7 changes: 4 additions & 3 deletions knp/base-framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ project(knp-base-framework VERSION "${KNP_VERSION}" LANGUAGES C CXX
set(${PROJECT_NAME}_PUBLIC_INCLUDE_DIR "knp/framework")

find_package(Boost ${KNP_BOOST_MIN_VERSION} COMPONENTS filesystem REQUIRED)
find_package(OpenCV REQUIRED)

include(GNUInstallDirs)
include(knp-functions)
Expand Down Expand Up @@ -77,13 +76,15 @@ knp_add_library("${PROJECT_NAME}-core"
impl/inference_evaluation/classification/processor.cpp
impl/observer.cpp
impl/logging.cpp
impl/visualizer/graph_physics.cpp
impl/visualizer/visualize_network.cpp
impl/visualizer/graph_helpers.cpp
impl/visualizer/dot_helpers.cpp
impl/visualizer/generate_files.cpp
${${PROJECT_NAME}_headers}
ALIAS KNP::BaseFramework::Core
LINK_PRIVATE
spdlog::spdlog_header_only Boost::headers Boost::filesystem HighFive hdf5-static csv2
${OpenCV_LIBS}
${GRAPHVIZ_LIBRARIES}
# Hack to build with CLang.
${ADD_LIBS}
LINK_PUBLIC
Expand Down
10 changes: 5 additions & 5 deletions knp/base-framework/impl/sonata/load_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,16 @@ std::vector<core::AllPopulationsVariant> load_populations(const fs::path &pop_h5

for (size_t i = 0; i < num_populations; ++i)
{
const std::string proj_name = group.getObjectName(i);
const std::string pop_name = group.getObjectName(i);
const int neuron_type =
group.getGroup(proj_name).getDataSet("node_type_id").read<std::vector<int>>()[0]; // One type only.
group.getGroup(pop_name).getDataSet("node_type_id").read<std::vector<int>>()[0]; // One type only.
// Check if type is in type_file.
if (neuron_type == get_neuron_type_id<neuron_traits::BLIFATNeuron>())
result.emplace_back(load_population<neuron_traits::BLIFATNeuron>(group, proj_name));
result.emplace_back(load_population<neuron_traits::BLIFATNeuron>(group, pop_name));
else if (neuron_type == get_neuron_type_id<neuron_traits::SynapticResourceSTDPBLIFATNeuron>())
result.emplace_back(load_population<neuron_traits::SynapticResourceSTDPBLIFATNeuron>(group, proj_name));
result.emplace_back(load_population<neuron_traits::SynapticResourceSTDPBLIFATNeuron>(group, pop_name));
else if (neuron_type == get_neuron_type_id<neuron_traits::AltAILIF>())
result.emplace_back(load_population<neuron_traits::AltAILIF>(group, proj_name));
result.emplace_back(load_population<neuron_traits::AltAILIF>(group, pop_name));
// TODO: Add other supported types or better use a template.
}
return result;
Expand Down
Loading