Skip to content

Commit

Permalink
sketch building graph (#155)
Browse files Browse the repository at this point in the history
#152

---------

Co-authored-by: AndreySorokin7 <[email protected]>
  • Loading branch information
Semyon1104 and AndreySorokin7 authored Dec 6, 2024
1 parent e2d3f10 commit f8c931c
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 42 deletions.
38 changes: 22 additions & 16 deletions app/AlexNet/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,34 @@
import numpy as np
import os

# Пути к модели и JSON файлу
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
MODEL_PATH = os.path.join(BASE_DIR, 'docs', 'AlexNet-model.h5')
MODEL_DATA_PATH = os.path.join(BASE_DIR, 'docs', 'model_data_alexnet_1.json')


# Загрузка модели
model = load_model(MODEL_PATH)

# Получение весов модели
weights = model.get_weights()


# Сохранение имен слоев и весов модели
layer_weights = {}
for layer in model.layers:
# Получение весов модели и информации о порядке слоев
layer_info = []
for index, layer in enumerate(model.layers):
layer_name = layer.name
layer_type = type(layer).__name__ # Тип слоя (например, Conv2D, Dense и т.д.)

# Преобразование весов в списки для совместимости с JSON
layer_weights[layer_name] = [w.tolist() for w in layer.get_weights()]
layer_weights = [w.tolist() for w in layer.get_weights()]

# Сохранение информации о слое: его тип, имя и веса
layer_info.append({
'index': index, # Порядковый номер слоя
'name': layer_name,
'type': layer_type,
'weights': layer_weights
})

# Сохранение данных в JSON файл
with open(MODEL_DATA_PATH, 'w') as f:
json.dump(layer_weights, f, indent=2) # добавляем отступы для лучшей читаемости
json.dump(layer_info, f, indent=2)

print(f"Model data saved to {MODEL_DATA_PATH}")

Expand All @@ -34,13 +40,13 @@
loaded_model_data = json.load(f)

# Преобразование данных обратно в numpy массивы
for layer_name, weights in loaded_model_data.items():
loaded_model_data[layer_name] = [np.array(w) for w in weights]
for layer_data in loaded_model_data:
layer_data['weights'] = [np.array(w) for w in layer_data['weights']]

# Вывод данных
print("Model layers and weights:")
for layer_name, weights in loaded_model_data.items():
print("Layer:", layer_name)
for weight in weights:
print("Model layers and weights with order:")
for layer_data in loaded_model_data:
print(f"Layer {layer_data['index']} ({layer_data['type']}, {layer_data['name']}):")
for weight in layer_data['weights']:
print(weight)
print()
15 changes: 10 additions & 5 deletions app/AlexNet/reader_weights_sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@ int main() {
std::string json_file = MODEL_PATH;
json model_data = read_json(json_file);

for (const auto& layer : model_data.items()) {
const std::string& layer_name = layer.key();
std::cout << "Layer: " << layer_name << std::endl;
for (const auto& layer_data : model_data) {
int layer_index = layer_data["index"];
std::string layer_name = layer_data["name"];
std::string layer_type = layer_data["type"];

std::cout << "Layer " << layer_index << " (" << layer_type << ", "
<< layer_name << "):" << std::endl;

try {
Tensor tensor = create_tensor_from_json(layer.value(), Type::kFloat);
std::cout << tensor << std::endl;
Tensor tensor =
create_tensor_from_json(layer_data["weights"], Type::kFloat);
// std::cout << tensor << std::endl;
} catch (const std::exception& e) {
std::cerr << "Error processing layer " << layer_name << ": " << e.what()
<< std::endl;
Expand Down
2 changes: 1 addition & 1 deletion app/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
add_subdirectory(ReaderImage)

add_subdirectory(Accuracy)
add_subdirectory(AlexNet)
add_subdirectory(Graph)
46 changes: 46 additions & 0 deletions app/Graph/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/3rdparty/opencv/build")

execute_process(
COMMAND ${CMAKE_COMMAND} -S "${CMAKE_SOURCE_DIR}/3rdparty/opencv" -B "${CMAKE_SOURCE_DIR}/3rdparty/opencv/build" -DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DBUILD_opencv_apps=OFF
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/3rdparty/opencv/build"
)
execute_process(
COMMAND ${CMAKE_COMMAND} --build "${CMAKE_SOURCE_DIR}/3rdparty/opencv/build" --config "${CMAKE_BUILD_TYPE}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/3rdparty/opencv/build"
)
set(INCLUDE_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/build.hpp")
set(SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/build.cpp")
add_library(BuildGraph STATIC ${INCLUDE_HEADERS} ${SRC_FILES})

set_target_properties(BuildGraph PROPERTIES LINKER_LANGUAGE CXX)

find_package(OpenCV REQUIRED PATHS "${CMAKE_SOURCE_DIR}/3rdparty/opencv/build")
include_directories(${OpenCV_INCLUDE_DIRS})

target_link_libraries(BuildGraph PUBLIC ${OpenCV_LIBS})
target_link_libraries(BuildGraph PUBLIC reader_lib)
target_link_libraries(BuildGraph PUBLIC TBB::tbb)
target_link_libraries(BuildGraph PUBLIC layers_lib)
target_link_libraries(BuildGraph PUBLIC gtest_main)

target_include_directories(BuildGraph PUBLIC ${CMAKE_SOURCE_DIR}/3rdparty/Json/include)

add_executable(Graph_Build graph_build.cpp)
target_link_libraries(Graph_Build BuildGraph)

if (WIN32)
add_custom_command(TARGET Graph_Build POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_SOURCE_DIR}/3rdparty/opencv/build/bin/${CMAKE_BUILD_TYPE}"
"${CMAKE_BINARY_DIR}/app/ReaderImage/${CMAKE_BUILD_TYPE}/")
endif()

file(DOWNLOAD
"https://raw.githubusercontent.com/opencv/opencv/4.x/samples/data/lena.jpg"
"${CMAKE_CURRENT_BINARY_DIR}/image.jpg"
SHOW_PROGRESS
STATUS status_code
LOG log_file
)
add_definitions(-DIMAGE1_PATH="${CMAKE_CURRENT_BINARY_DIR}/image.jpg")
add_definitions(-DMODEL_PATH="${CMAKE_SOURCE_DIR}/docs/model_data_alexnet_1.json")
132 changes: 132 additions & 0 deletions app/Graph/build.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include "build.hpp"

void build_graph(Tensor& input, Tensor& output) {
std::vector<std::shared_ptr<Layer>> layers;

std::string json_file = MODEL_PATH;
json model_data = read_json(json_file);

std::cout << "Loaded model data from JSON." << std::endl;

for (const auto& layer_data : model_data) {
std::string layer_type = layer_data["type"];
std::cout << "Processing layer of type: " << layer_type << std::endl;

Tensor tensor =
create_tensor_from_json(layer_data["weights"], Type::kFloat);

if (layer_type.find("Conv") != std::string::npos) {
Shape shape = tensor.get_shape();
std::cout << "PoolingLayer shape: ";
for (size_t i = 0; i < shape.dims(); ++i) {
std::cout << shape[i] << " ";
}
std::cout << std::endl;

Tensor tmp_values = tensor;
Tensor tmp_bias = make_tensor(tensor.get_bias());

auto conv_layer =
std::make_shared<ConvolutionalLayer>(1, 0, 1, tmp_values, tmp_bias);
conv_layer->setName(kConvolution);
layers.push_back(conv_layer);
std::cout << "ConvLayer added to layers." << std::endl;
}

if (layer_type.find("Dense") != std::string::npos) {
Tensor tmp_values = tensor;
std::vector<float> values_vector = *tensor.as<float>();
std::vector<std::vector<float>> values_vector_2d(
tensor.get_shape()[0],
std::vector<float>(tensor.get_shape()[1], 0.0F));
int q = 0;
for (size_t i = 0; i < values_vector.size(); i++) {
values_vector_2d[q][i - (q * tensor.get_shape()[1])] = values_vector[i];
if ((i + 1) % tensor.get_shape()[1] == 0) {
q++;
}
}
std::vector<std::vector<float>> values_vector_2d_2(
tensor.get_shape()[1],
std::vector<float>(tensor.get_shape()[0], 0.0F));

for (size_t i = 0; i < tensor.get_shape()[0]; ++i) {
for (size_t j = 0; j < tensor.get_shape()[1]; ++j) {
values_vector_2d_2[j][i] = values_vector_2d[i][j];
}
}
std::vector<float> values_vector_1d(
tensor.get_shape()[0] * tensor.get_shape()[1], 0.0F);
int index_1d = 0;

for (size_t j = 0; j < tensor.get_shape()[1]; ++j) {
for (size_t k = 0; k < tensor.get_shape()[0]; ++k) {
values_vector_1d[index_1d++] = values_vector_2d_2[j][k];
}
}

Shape shape_fc({tensor.get_shape()[1], tensor.get_shape()[0]});
Tensor values = make_tensor<float>(values_vector_1d, shape_fc);
Tensor tmp_bias = make_tensor(tensor.get_bias());

auto fc_layer = std::make_shared<FCLayer>(values, tmp_bias);
fc_layer->setName(kFullyConnected);
layers.push_back(fc_layer);
std::cout << "DenseLayer added to layers." << std::endl;
}

if (layer_type.find("Pool") != std::string::npos) {
Shape shape = {2, 2};
std::cout << "PoolingLayer shape: " << shape[0] << "x" << shape[1]
<< std::endl;
auto pool_layer = std::make_shared<PoolingLayer>(shape);
pool_layer->setName(kPooling);
layers.push_back(pool_layer);
std::cout << "PoolingLayer added to layers." << std::endl;
}

if (layer_type.find("Flatten") != std::string::npos) {
auto flatten_layer = std::make_shared<FlattenLayer>();
flatten_layer->setName(kFlatten);
layers.push_back(flatten_layer);
std::cout << "FlattenLayer added to layers." << std::endl;
}

if (layer_type.find("Dropout") != std::string::npos) {
auto dropout_layer = std::make_shared<DropOutLayer>(0.5);
dropout_layer->setName(kDropout);
layers.push_back(dropout_layer);
std::cout << "DropOutLayer added to layers with probability 0.5."
<< std::endl;
}
}
std::cout << "number of layers - " << layers.size() + 1 << std::endl;
Graph graph(static_cast<int>(layers.size()));
InputLayer a1(kNhwc, kNchw, 1, 2);

std::cout << "InputLayer created." << std::endl;

graph.setInput(a1, input);
std::cout << "Input set in graph." << std::endl;

graph.makeConnection(a1, *layers[0]);
std::cout << "Connection made between InputLayer and first layer."
<< std::endl;

for (size_t i = 0; i < layers.size() - 1; ++i) {
graph.makeConnection(*layers[i], *layers[i + 1]);
}

graph.setOutput(*layers.back(), output);
std::cout << "Output set in graph." << std::endl;

std::cout << "Starting inference..." << std::endl;
graph.inference();
std::cout << "Inference completed." << std::endl;

std::vector<float> tmp = *output.as<float>();
std::vector<float> tmp_output = softmax<float>(*output.as<float>());
for (float i : tmp) {
std::cout << i << " ";
}
}
18 changes: 18 additions & 0 deletions app/Graph/build.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <iostream>
#include <opencv2/opencv.hpp>
#include <stdexcept>
#include <variant>
#include <vector>

#include "Weights_Reader/reader_weights.hpp"
#include "graph/graph.hpp"
#include "layers/ConvLayer.hpp"
#include "layers/DropOutLayer.hpp"
#include "layers/EWLayer.hpp"
#include "layers/FCLayer.hpp"
#include "layers/FlattenLayer.hpp"
#include "layers/InputLayer.hpp"
#include "layers/OutputLayer.hpp"
#include "layers/PoolingLayer.hpp"

void build_graph(Tensor& input, Tensor& output);
40 changes: 40 additions & 0 deletions app/Graph/graph_build.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "build.cpp"
#include "build.hpp"

using namespace itlab_2023;

int main() {
std::string image_path = IMAGE1_PATH;
cv::Mat image = cv::imread(image_path);
if (image.empty()) {
throw std::runtime_error("Failed to load image");
}
cv::Mat resized_image;
cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
cv::resize(image, resized_image, cv::Size(28, 28));
std::vector<cv::Mat> channels;

cv::split(resized_image, channels);

int count_pic = 1;
std::vector<float> res(count_pic * 28 * 28);

for (int i = 0; i < 28; ++i) {
for (int j = 0; j < 28; ++j) {
res[i * 28 + j] = channels[0].at<uchar>(i, j);
}
}
Shape sh({static_cast<size_t>(count_pic), 28, 28, 1});
Tensor t = make_tensor<float>(res, sh);
Tensor input = t;

Shape sh1({1, 5, 5, 3});
std::vector<float> vec;
vec.reserve(75);
for (int i = 0; i < 75; ++i) {
vec.push_back(3);
}
Tensor output = make_tensor(vec, sh1);

build_graph(input, output);
}
3 changes: 1 addition & 2 deletions include/Weights_Reader/reader_weights.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ using namespace itlab_2023;
json read_json(const std::string& filename);
void extract_values_without_bias(const json& j, std::vector<float>& values);
void extract_values_from_json(const json& j, std::vector<float>& values);
void parse_json_shape(const json& j, std::vector<size_t>& shape,
size_t dim = 0);
void parse_json_shape(const json& j, std::vector<size_t>& shape, size_t dim);
Tensor create_tensor_from_json(const json& j, Type type);
void extract_bias_from_json(const json& j, std::vector<float>& bias);
1 change: 1 addition & 0 deletions include/graph/graph.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

#pragma once
#include <algorithm>
#include <chrono>
Expand Down
2 changes: 2 additions & 0 deletions include/layers/Layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ enum LayerType {
kElementWise,
kConvolution,
kFullyConnected,
kFlatten,
kOutput,
};

class Layer {
public:
Layer() = default;
virtual ~Layer() = default;
int getID() const { return id_; }
void setID(int id) { id_ = id; }
LayerType getName() const { return type_; }
Expand Down
4 changes: 4 additions & 0 deletions include/layers/Shape.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

#include <algorithm>
#include <initializer_list>
#include <iostream>
#include <numeric>
#include <ostream>
#include <stdexcept>
#include <vector>

Expand Down Expand Up @@ -37,8 +39,10 @@ class Shape {
}
size_t dims() const noexcept { return dims_.size(); }
size_t get_index(const std::vector<size_t>& coords) const;
friend std::ostream& operator<<(std::ostream& os, const Shape& shape);

private:
std::vector<size_t> dims_;
};

} // namespace itlab_2023
1 change: 1 addition & 0 deletions include/layers/Tensor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class Tensor {
}

const std::vector<float>& get_bias() const { return bias_; }
const std::vector<uint8_t>& get_values() const { return values_; }

bool empty() const { return values_.empty(); }
auto begin() { return values_.begin(); }
Expand Down
Loading

0 comments on commit f8c931c

Please sign in to comment.