Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes 1.0 #316

Merged
merged 21 commits into from
Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5dbdf92
Added Repeat layer to ONNX as Tile operator
chavicoski Dec 1, 2021
a8e5138
Fixed bug with losses and metrics when using more than one output lay…
chavicoski Dec 1, 2021
b7c9b1a
Add ONNX simplifier as a runtime dependency
salvacarrion Dec 1, 2021
1fb0735
Update ONNX simplifier documentation
salvacarrion Dec 1, 2021
21200f7
Add protobuf
salvacarrion Dec 1, 2021
cabc27b
Update eigen to 3.4.0
salvacarrion Dec 1, 2021
1500425
Minor improvements (docs)
salvacarrion Dec 1, 2021
e3a061d
Update progress
salvacarrion Dec 1, 2021
9f87012
Remove transpose layer (deprecated since a long time. Now is permute)
salvacarrion Dec 1, 2021
aa24ea9
Merge remote-tracking branch 'origin/develop' into develop
salvacarrion Dec 1, 2021
92b5dd7
Minor changes
salvacarrion Dec 1, 2021
291f759
Add app test model
salvacarrion Dec 1, 2021
c4b7faa
Improve error format
salvacarrion Dec 1, 2021
5578520
Change types from unsigned int to int (it is problematic with OMP)
salvacarrion Dec 1, 2021
cf0e2c5
Add functions: replace_str and normalize_layer_name
salvacarrion Dec 1, 2021
9d63f46
Normalize layer names due to some problem with graphviz
salvacarrion Dec 1, 2021
e48ab24
Fixed bug when exporting gradients from CPU
chavicoski Dec 1, 2021
41a0129
Merge branch 'develop' of https://github.com/deephealthproject/eddl i…
chavicoski Dec 1, 2021
3ef44e4
Change onnx pad_layer_name
salvacarrion Dec 1, 2021
29dd6b2
Merge remote-tracking branch 'origin/develop' into develop
salvacarrion Dec 1, 2021
ea3f24e
Merge branch 'master' into develop
salvacarrion Dec 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions cmake/eigen.CMakeLists.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@ project(eigen-download NONE)
# Set base dir
SET(EP_BASE_DIR @EP_BASE_DIR@)

if(CMAKE_GENERATOR MATCHES "Visual Studio")
# Visual Studio needs a more recent version of Eigen3
# Version 3.3.90
SET(TAG ba9d18b9388acdf27a3900a4f981fab587e59b0c)
else()
SET(TAG "3.3.7") # Eigen3 must be >= 3.3.7
endif()
SET(TAG "3.4.0")

include(ExternalProject)
ExternalProject_Add(eigen
Expand Down
11 changes: 7 additions & 4 deletions docs/markdown/eddl_progress.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@
| Expand | 🟢️️| 🟢️️ |🟢️️ | 🟢️ | Returns a layer with singleton dimensions expanded to a larger size |
| Where | 🟢️️ | 🟢️️ | 🟢️️ | ️🔴️ | Return elements chosen from x or y depending on condition |
| Resize | 🟢️️ | 🟢️️ |🟢️️ | 🟢️️ | Resize the input image to the given size. `[height, width]` |
| Clamp / Clip | 🟢️️ | 🟢️️ |🟢️️ | 🔴️️ | Clamps all elements in input into the range `[min, max]`. |
| Repeat | 🟢️️ | 🟢️️ |🟢️️ | 🔴️️ | Repeats the elements of a tensor along the specified dimension. |


| Clamp / Clip | 🟢️️ | 🟢️️ |🟢️️ | 🟢️ | Clamps all elements in input into the range `[min, max]`. |
| Repeat | 🟢️️ | 🟢️️ |🟢️️ | 🔴️️ | Repeats the elements of a tensor along the specified dimension. (Elements in an axis can be repeated independently) |
| Tile | 🔴️️ | 🔴 |🔴️ | 🔴️️ | Repeats the elements of a tensor along the specified dimensions. |
| Round | 🔴️️ | 🔴️️ | 🔴️️ | 🔴️️ | Round of the elements of input |
| Ceil | 🔴️ | 🔴️️ | 🔴️ | 🔴️️ | Ceil of the elements of input |
| Floor | 🔴️️ | 🔴 |🔴️ | 🔴️️ | Floor of the elements of input |
| Broadcast | 🔴️️ | 🔴 |🔴️ | 🔴️️ | Produce an object that mimics broadcasting. |


## Activations
Expand Down
3 changes: 2 additions & 1 deletion docs/markdown/eddl_progress_tensor.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,9 @@ Numpy-like operations over a raw-tensor object

| Functionality | CPU | GPU | Comments |
| ------------- | ---- | ---- | -------- |
| tile | ⚫️ | ⚫️ | Construct an array by repeating A the number of times given by reps |
| repeat | 🟢️ | 🟢️️️ ️ | Repeats the elements of a tensor along the specified dimension |
| tile | 🔴️️ | 🔴️️️ ️ | Repeats the elements of a tensor along the specified dimensions |
| broadcast | 🔴️️ | 🔴️️️ ️ | Produce an object that mimics broadcasting. |


### Adding and removing elements
Expand Down
5 changes: 4 additions & 1 deletion docs/sphinx/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,7 @@

# html_sidebars = {
# '**': ['searchbox.html'],
# }
# }


github_url = "https://github.com/deephealthproject/eddl"
2 changes: 2 additions & 0 deletions docs/sphinx/source/intro/build-options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ If you decide to manually install these dependencies in your system (make sure t
- sphinx_rtd_theme==1.0.*
- sphinx-tabs==3.2.*
- breathe==4.31.*
- onnx-simplifier==0.3.*
- protobuf==3.19.*

.. note::

Expand Down
12 changes: 12 additions & 0 deletions docs/sphinx/source/intro/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ You can also install ``EDDL`` from source with cmake.
# -DCMAKE_C_COMPILER=$(which gcc-7) \
# -DCMAKE_CXX_COMPILER=$(which g++-7) \

make -j$(nproc) # The -j flag is to parallelize the compilation
make install

.. tab:: MacOS
Expand All @@ -142,6 +143,7 @@ You can also install ``EDDL`` from source with cmake.
cd build
cmake .. -DCMAKE_PREFIX_PATH=$CONDA_PREFIX -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX

make -j$(sysctl -n hw.logicalcpu) # The -j flag is to parallelize the compilation
make install

.. tab:: Windows
Expand Down Expand Up @@ -186,6 +188,16 @@ See the :doc:`build-options` section for more details about cmake options.

cmake .. -DBUILD_SUPERBUILD=ON -DBUILD_TARGET=CUDNN -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc -DCMAKE_CXX_COMPILER=/usr/bin/g++-7

6. To update/remote the eddl environment type:

.. code:: bash

# Update existing environment
conda env update --file environment.yml --prune

# Remove environment
conda remove --name eddl --all


Including EDDL in your project
---------------------------------
Expand Down
2 changes: 2 additions & 0 deletions docs/sphinx/source/model/onnx.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ you try to "standardize" or "simplifying" using *onnx_simplifier_*.

**Installation**

This is only needed is you are not using the conda environment for the EDDL, as we ship ONNX simplifier with it.

.. code-block:: bash

pip3 install -U pip && pip3 install onnx-simplifier
Expand Down
4 changes: 3 additions & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ dependencies: # https://docs.conda.io/projects/conda-build/en/latest/resources/
- sphinx==4.3.*
- sphinx_rtd_theme==1.0.*
- sphinx-tabs==3.2.*
- breathe==4.31.*
- breathe==4.31.*
- onnx-simplifier==0.3.*
- protobuf==3.19.*
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ if(BUILD_PROTOBUF)
add_executable(app_image_classification_resnet34 "applications/1_image_classification_resnet34.cpp")
target_link_libraries(app_image_classification_resnet34 eddl)

add_executable(app_test_model "applications/app_test_model.cpp")
target_link_libraries(app_test_model eddl)


# EXAMPLES: RAW ONNX **************************************************************
add_executable(onnx_pointer "onnx/1_onnx_pointer.cpp")
Expand Down
181 changes: 181 additions & 0 deletions examples/applications/app_test_model.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@

#include <iostream>
#include "eddl/apis/eddl.h"
#include "eddl/serialization/onnx/eddl_onnx.h"

using namespace eddl;


Tensor* preprocess_input(Tensor* input, const vector<int> &target_size, bool normalize=true, bool standarize=true){
// Define preprocessing constants
auto* mean_vec = new Tensor( {0.485, 0.456, 0.406}, {3, 1}, input->device);
auto* std_vec = new Tensor( {0.229, 0.224, 0.225}, {3, 1}, input->device);

// ==========================================================================
// ====== SANITY CHECKS =====================================================
// ==========================================================================
// Check dimension. Input must be a 3D or 4D tensor
if(!(input->ndim == 3 || input->ndim == 4)){
throw std::runtime_error("A 3D or 4D tensor is expected. " + std::to_string(input->ndim) + "D tensor received.");
}

// Convert from 3D to 4D (if needed)
if(input->ndim == 3){
input->unsqueeze_(0);
}
// ==========================================================================


// ==========================================================================
// ====== NORMALIZATION =====================================================
// ==========================================================================

// Resize tensor (creates a new instance)
Tensor* new_input = input->scale(target_size); // (height, width)

// Normalization [0..1]
if(normalize){
new_input->mult_(1/255.0f);
}

// Standarization: (X-mean)/std
if(standarize){
// Tensor* mean = Tensor::broadcast(mean_vec, new_input);
// Tensor* std = Tensor::broadcast(std_vec, new_input);
// 1) [There is no broadcasting...] Repeat dimensions => Temp!
Tensor* mean = Tensor::repeat(mean_vec, target_size[0]*target_size[1], 1); mean->reshape_(new_input->shape);
Tensor* std = Tensor::repeat(std_vec, target_size[0]*target_size[1], 1); std->reshape_(new_input->shape);
new_input->sub_(mean);
new_input->div_(std);

// Free memory
delete mean;
delete std;
}
// ==========================================================================

// Free memory
delete mean_vec;
delete std_vec;

return new_input;
}


int main(int argc, char **argv) {
// ==========================================================================
// ====== SET DEFAULT VARIABLES =============================================
// ==========================================================================

// Step 0: Download the model, the classes and the image we want to classify
string image_fname = "../../examples/data/elephant.jpg";
string class_names_file = "../../examples/data/imagenet_class_names.txt";

// Image Classification
string model_path = "models/resnet34-v1-7.onnx"; // 3x224x224 // okay
// string model_path = "models/mobilenetv2-7.onnx"; // 3x224x224 // Signal: SIGSEGV (Segmentation fault)
// string model_path = "models/vgg16-7.onnx"; // 3xHxW // okay
// string model_path = "models/bvlcalexnet-3.onnx"; // 3x224x224 // The onnx node 'LRN' is not supported yet
// string model_path = "models/bvlcalexnet-12.onnx"; // 3x224x224 // The onnx node 'LRN' is not supported yet
// string model_path = "models/googlenet-3.onnx"; // 3x224x224 // The onnx node 'LRN' is not supported yet
// string model_path = "models/densenet-3.onnx"; // 3x224x224 // okay
// string model_path = "models/inception-v1-3.onnx"; // 3x224x224 // The onnx node 'LRN' is not supported yet
// string model_path = "models/efficientnet-lite4-11.onnx"; // 224x224x3 // The onnx node 'LRN' is not supported yet

// Object Detection & Image Segmentation
// string model_path = "models/tinyyolov2-7.onnx"; // 3x416x416 //Error in Add node Add. The first dimension (batch) of the constant operator must be 1, got 3 (ONNX::ImportNet) ⚠️
// string model_path = "models/ssd-10_simp.onnx"; // 3x1200x1200 // Signal: SIGSEGV (Segmentation fault)
// string model_path = "models/FasterRCNN-10_simp.onnx"; // 3xHxW // Signal: SIGSEGV (Segmentation fault)
// string model_path = "models/yolov4_simp.onnx"; // 416x416x3 // [ONNX::LOG] Detected a padding asymmetry + The onnx node 'Shape' is not supported yet
// string model_path = "models/MaskRCNN-10_simp.onnx"; // 3xHxW // Signal: SIGSEGV (Segmentation fault)
// string model_path = "models/retinanet-9.onnx"; // 3xHxW // okay
// string model_path = "models/yolov3-10_simp.onnx"; // 3x416x416 // The imported model has more than 1 input layer and the shape provided to reshape the model can only be appliedif the model has only one input layer. (ONNX::ImportNet)
// string model_path = "models/fcn-resnet50-11_simp.onnx"; // 3xHxW // The onnx node 'Shape' is not supported yet
// string model_path = "models/ResNet101-DUC-7.onnx"; // 3xHxW // okay. Error with plot

// Image Manipulation
// string model_path = "models/super-resolution-10.onnx"; // 3x224x224 // Tensors with different size (Tensor::copy)
// string model_path = "models/mosaic-9.onnx"; // 3xHxW // Error importing layer . Only "constant" mode is supported (passed "reflect"). (ONNX::ImportNet)

// Step 1: Specify input
int in_channels = 3;
int in_height = 224;
int in_width = 224;
vector<int> input_shape = {in_channels, in_height, in_width};
vector<int> dimensions_order = {0, 1, 2, 3};
// ==========================================================================


// ==========================================================================
// ====== LOAD ONNX MODEL ===================================================
// ==========================================================================

// Import ONNX model
std::cout << "Importing ONNX..." << std::endl;
Net *net = import_net_from_onnx_file(model_path, input_shape);

// ==========================================================================
// Print and plot our model
net->summary();
net->plot("mymodel.pdf");

// ==========================================================================
// ====== APPLY POSTPROCESSING ==============================================
// ==========================================================================

// Step 4 (optional): Add a softmax layer to get probabilities directly from the model, since it
// does not include the softmax layer.
// layer input = net->lin[0]; // getLayer(net,"input_layer_name");
// layer output = net->lout[0]; // getLayer(net,"output_layer_name");
// layer new_output = Softmax(output);
//
// // Create model
// net = Model({input},{new_output});
// ==========================================================================

// ==========================================================================
// ====== COMPILE MODEL =====================================================
// ==========================================================================

// Build model
build(net,
adam(0.001f), // Optimizer (not used for prediction)
{"softmax_cross_entropy"},// Losses (not used for prediction)
{"categorical_accuracy"}, // Metrics (not used for prediction)
CS_GPU({1}), // Use one GPU
false // Disable model initialization, since we want to use the onnx weights
);
// ==========================================================================


// ==========================================================================
// ====== INFERENCE =========================================================
// ==========================================================================
// Load test image
Tensor *image = Tensor::load(image_fname);

// Step 3: Preprocess input. (Look up the preprocessing required at the model's page)
Tensor* image_preprocessed = preprocess_input(image, {in_height, in_width});
image_preprocessed->permute_(dimensions_order);

// Predict image. Returns a vector of tensors (here one).
vector<Tensor*> outputs = net->predict({image_preprocessed});
// ==========================================================================


// ==========================================================================
// ====== PRINT TOP K CLASSES ===============================================
// ==========================================================================
// Read imagenet class names from txt file
std::cout << "Reading imagenet class names..." << std::endl;
vector<string> class_names = eddl::read_txt_file(class_names_file);

// Print top K predictions
int top_k = 5;
std::cout << "Top " << top_k << " predictions:" << std::endl;
std::cout << eddl::get_topk_predictions(outputs[0], class_names, top_k) << std::endl;
// ==========================================================================

return 0;
}

5 changes: 4 additions & 1 deletion examples/test_internals/onnx/test_onnx_auxiliar_layers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ int main(int argc, char **argv) {
layer l = in; // Aux var

l = Reshape(l, {1, 28, 28});
l = Repeat(l, 3, 0);
l = Repeat(l, 2, 1);
l = Repeat(l, 2, 2);
l = Pad(l, {1, 1, 1, 1}, 0.0);
l = MaxPool2D(ReLu(Conv2D(l, 30, {3, 3}, {1, 1}, "valid")), {3, 3}, {1, 1}, "same");

Expand Down Expand Up @@ -194,4 +197,4 @@ int main(int argc, char **argv) {
return EXIT_SUCCESS;
else
return EXIT_FAILURE;
}
}
29 changes: 29 additions & 0 deletions include/eddl/serialization/onnx/layers/core/repeat_onnx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#if defined(cPROTO)
#ifndef EDDL_REPEAT_ONNX_H
#define EDDL_REPEAT_ONNX_H
#include "eddl/serialization/onnx/onnx.pb.h"
#include "eddl/serialization/onnx/utils_onnx.h"
#include "eddl/layers/core/layer_core.h"

/*
* ONNX IMPORT
*/

// OPSET: 13, 6
Layer* build_repeat_layer(onnx::NodeProto *node,
map<string, onnx::NodeProto *> &constant_node_map,
map<string, vector<float>> &map_init_values,
map<string, Layer *> &output_node_map,
LOG_LEVEL log_level,
int dev,
int mem);

/*
* ONNX EXPORT
*/

// OPSET: 13, 6
void build_tile_node(LRepeat *layer, onnx::GraphProto *graph);

#endif // EDDL_REPEAT_ONNX_H
#endif // cPROTO
3 changes: 2 additions & 1 deletion include/eddl/serialization/onnx/layers/layers_onnx.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ enum ONNX_LAYERS {
SLICE, // OPSET: 13, 11, 10
SPLIT, // OPSET: 13, 11, 2
EXPAND, // OPSET: 13, 8
CONSTANT // OPSET: 13, 12, 11, 9, 1
CONSTANT, // OPSET: 13, 12, 11, 9, 1
REPEAT // OPSET: 13, 6
};

map<string, ONNX_LAYERS> create_enum_map();
Expand Down
12 changes: 8 additions & 4 deletions include/eddl/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,27 @@ bool pathExists(const std::string &s);

string get_parent_dir(const string& fname);

string replace_str(const string& value, const string& oldvalue, const string& newvalue);

string normalize_layer_name(const string& value);

vector<int> compute_squeeze(vector<int> shape, int axis, bool ignore_batch=false);
vector<int> compute_unsqueeze(vector<int> shape, int axis, bool ignore_batch=false);

vector<int> address2indices(unsigned int address, const vector<int>& shape, const vector<int>& strides);
vector<int> address2indices(int address, const vector<int>& shape, const vector<int>& strides);
unsigned int indices2address(const vector<int>& indices, const vector<int>& strides);

// https://isocpp.org/wiki/faq/inline-functions#inline-member-fns
inline int fast_indices2address(const unsigned int* indices, const unsigned int* strides, unsigned int ndim){
unsigned int address = 0;
inline int fast_indices2address(const int* indices, const int* strides, int ndim){
int address = 0;
for (int i=0; i< ndim; i++){
address += indices[i] * strides[i];
}
return address;
}


inline void fast_address2indices( int address, unsigned int* indices, const unsigned int* shape, const unsigned int* strides, unsigned int ndim){
inline void fast_address2indices( int address, int* indices, const int* shape, const int* strides, int ndim){
for(int i=0; i<ndim; i++) {
indices[i] = address / strides[i] % shape[i];
}
Expand Down
Loading