Skip to content
Snippets Groups Projects

version 0.2.0

Merged Maxence Naud requested to merge dev into main
Files
50
import unittest
import gzip
import numpy as np
from pathlib import Path
import aidge_core
import aidge_backend_cpu
import aidge_onnx
import aidge_quantization
from aidge_core import Log, Level
# --------------------------------------------------------------
# CONFIGS
# --------------------------------------------------------------
@@ -52,12 +55,13 @@ class test_ptq(unittest.TestCase):
# load the samples / labels (numpy)
self.samples = np.load(gzip.GzipFile('assets/mnist_samples.npy.gz', "r"))
self.labels = np.load(gzip.GzipFile('assets/mnist_labels.npy.gz', "r"))
curr_file_dir = Path(__file__).parent.resolve()
self.samples = np.load(gzip.GzipFile(curr_file_dir / 'assets/mnist_samples.npy.gz', "r"))
self.labels = np.load(gzip.GzipFile(curr_file_dir / 'assets/mnist_labels.npy.gz', "r"))
# load the model in AIDGE
self.model = aidge_onnx.load_onnx("assets/" + MODEL_NAME, verbose=False)
self.model = aidge_onnx.load_onnx(curr_file_dir / "assets/" / MODEL_NAME, verbose=False)
aidge_core.remove_flatten(self.model)
self.model.set_datatype(aidge_core.dtype.float32)
@@ -69,15 +73,16 @@ class test_ptq(unittest.TestCase):
def test_model(self):
Log.set_console_level(Level.Info)
# compute the base accuracy
accuracy = compute_accuracy(self.model, self.samples[0:NB_SAMPLES], self.labels)
self.assertAlmostEqual(accuracy * 100, ACCURACIES[0], msg='base accuracy does not meet the baseline !', delta=0.1)
def test_quant_model(self):
# create the calibration dataset
Log.set_console_level(Level.Info)
# create the calibration dataset
tensors = []
for sample in self.samples[0:NB_SAMPLES]:
sample = prepare_sample(sample)
@@ -109,4 +114,4 @@ class test_ptq(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
unittest.main()
function(generate_python_binding name target_to_bind)
function(generate_python_binding pybind_module_name target_to_bind)
add_definitions(-DPYBIND)
Include(FetchContent)
set(PYBIND_VERSION v2.10.4)
set(PYBIND11_FINDPYTHON ON)
message(STATUS "Retrieving pybind ${PYBIND_VERSION} from git")
FetchContent_Declare(
PyBind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git
GIT_TAG v2.10.4 # or a later release
PyBind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git
GIT_TAG ${PYBIND_VERSION} # or a later release
)
# Use the New FindPython mode, recommanded. Requires CMake 3.15+
find_package(Python COMPONENTS Interpreter Development)
find_package(Python COMPONENTS Interpreter Development.Module)
FetchContent_MakeAvailable(PyBind11)
message(STATUS "Creating binding for module ${name}")
message(STATUS "Creating binding for module ${pybind_module_name}")
file(GLOB_RECURSE pybind_src_files "python_binding/*.cpp")
pybind11_add_module(${name} MODULE ${pybind_src_files} "NO_EXTRAS") # NO EXTRA recquired for pip install
target_include_directories(${name} PUBLIC "python_binding")
target_link_libraries(${name} PUBLIC ${target_to_bind})
pybind11_add_module(${pybind_module_name} MODULE ${pybind_src_files} "NO_EXTRAS") # NO EXTRA recquired for pip install
target_include_directories(${pybind_module_name} PUBLIC "python_binding")
target_link_libraries(${pybind_module_name} PUBLIC ${target_to_bind})
endfunction()
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_CPU_OPERATOR_DOREFAIMPL_H_
#define AIDGE_CPU_OPERATOR_DOREFAIMPL_H_
#include <cstddef> // std::size_t
#include <memory>
#include <tuple> // std::tuple
#include <vector>
#include "aidge/backend/cpu/operator/OperatorImpl.hpp"
#include "aidge/operator/SAT/DoReFa.hpp"
#include "aidge/utils/Registrar.hpp"
#include "aidge/utils/Types.h"
namespace Aidge {
// Operator implementation entry point for the backend
using DoReFaImpl_cpu = OperatorImpl_cpu<DoReFa_Op,
void(const std::size_t, float, DoReFaMode, const void*, void*),
void(const std::size_t, float, DoReFaMode, const void*, const void*, void*)>;
// Implementation entry point registration to Operator
REGISTRAR(DoReFa_Op, "cpu", Aidge::DoReFaImpl_cpu::create);
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_DOREFAIMPL_H_ */
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_CPU_OPERATOR_DOREFAIMPL_FORWARD_KERNEL_H_
#define AIDGE_CPU_OPERATOR_DOREFAIMPL_FORWARD_KERNEL_H_
#include "aidge/utils/Registrar.hpp"
#include "aidge/backend/cpu/operator/SAT/DoReFaImpl.hpp"
namespace Aidge {
template <class I, class O>
void DoReFaImpl_cpu_forward_kernel(std::size_t inputLength,
float range,
DoReFaMode mode,
const void* input_,
void* output_)
{
const I* input = static_cast<const I*>(input_);
O* output = static_cast<O*>(output_);
// Dorefa Quantization
//#pragma omp parallel for if (inputLength > 1024)
for (unsigned int i = 0; i < inputLength; ++i) {
if (mode == DoReFaMode::Default) {
auto q = I(0.5) * (input[i] + I(1.0));
q = O(1.0f / range) * O(std::rintf(q * range));
output[i] = q * O(2.0) - O(1.0);
}
else {
output[i] = O(1.0f / range) * O(std::rintf(input[i] * range));
}
}
}
template <class I, class GI, class GO>
void DoReFaImpl_cpu_backward_kernel(const std::size_t inputLength,
float /*range*/,
DoReFaMode /*mode*/,
const void* /*input_*/,
const void* grad_output_,
void* grad_input_)
{
const GO* grad_output = static_cast<const GO*>(grad_output_);
GI* grad_input = static_cast<GI*>(grad_input_);
//#pragma omp parallel for if (inputLength > 1024)
for (unsigned int i = 0; i < inputLength; ++i) {
grad_input[i] = grad_output[i];
}
}
// Kernels registration to implementation entry point
REGISTRAR(DoReFaImpl_cpu,
{{DataType::Int32, DataFormat::NCHW}, {DataType::Int32, DataFormat::NCHW}},
{ProdConso::inPlaceModel, Aidge::DoReFaImpl_cpu_forward_kernel<int, int>, Aidge::DoReFaImpl_cpu_backward_kernel<int, int, int>});
REGISTRAR(DoReFaImpl_cpu,
{{DataType::Float32, DataFormat::NCHW}, {DataType::Float32, DataFormat::NCHW}},
{ProdConso::inPlaceModel, Aidge::DoReFaImpl_cpu_forward_kernel<float, float>, Aidge::DoReFaImpl_cpu_backward_kernel<float, float, float>});
REGISTRAR(DoReFaImpl_cpu,
{{DataType::Float64, DataFormat::NCHW}, {DataType::Float64, DataFormat::NCHW}},
{ProdConso::inPlaceModel, Aidge::DoReFaImpl_cpu_forward_kernel<double, double>, Aidge::DoReFaImpl_cpu_backward_kernel<double, double, double>});
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_DOREFAIMPL_FORWARD_KERNEL_H_ */
@@ -26,7 +26,7 @@ namespace Aidge
/**
* @brief Kind of clipping policy to apply during the activation quantization
*/
enum Clipping {MAX = 1, MSE, AA, KL};
enum class Clipping {MAX = 1, MSE, AA, KL};
/**
* @brief Compute the histograms of the activations of each node contained in the map of the ranges (passed as argument).
@@ -26,12 +26,12 @@ namespace Aidge {
/**
* @brief Set of the types of the nodes which contain affine transforms (that is Y = A.X + B)
*/
static const std::set<std::string> affineNodeTypes({"FC", "Conv", "ConvDepthWise", "PaddedConv", "PaddedConvDepthWise"});
static const std::set<std::string> affineNodeTypes({"FC", "Conv2D", "ConvDepthWise2D", "PaddedConv2D", "PaddedConvDepthWise2D"});
/**
* @brief Set of the types of the nodes which does not affect the PTQ process
*/
static const std::set<std::string> seamlessNodeTypes({"Pad", "MaxPooling", "AvgPooling", "PaddedMaxPooling", "PaddedAvgPooling", "GlobalAveragePooling", "Reshape", "Transpose", "Gather"});
static const std::set<std::string> seamlessNodeTypes({"Pad2D", "MaxPooling2D", "AvgPooling2D", "PaddedMaxPooling2D", "PaddedAvgPooling2D", "GlobalAveragePooling", "Reshape", "Transpose", "Gather"});
/**
* @brief Set of the types of the nodes that merge multiple branches into one
@@ -74,6 +74,10 @@ namespace Aidge {
*/
bool checkArchitecture(std::shared_ptr<GraphView> graphView);
void prepareNetwork(std::shared_ptr<GraphView> graphView);
/**
* @brief Insert a scaling node after each affine node of the GraphView.
* Also insert a scaling node in every purely residual branches.
@@ -154,7 +158,6 @@ namespace Aidge {
* @param graphView The GraphView under test.
*/
void devPTQ(std::shared_ptr<GraphView> graphView);
}
#endif /* AIDGE_QUANTIZATION_PTQ_PTQ_H_ */
+ 50
0
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_QUANTIZATION_QAT_FIXEDQ_H_
#define AIDGE_QUANTIZATION_QAT_FIXEDQ_H_
#include "aidge/graph/Node.hpp"
#include "aidge/graph/GraphView.hpp"
#include "aidge/data/Tensor.hpp"
namespace Aidge {
namespace QuantFixedQ {
/**
* @brief Insert the FixedQ quantizer nodes in a given GraphView
* @param graphView The GraphView containing the graph to quantize.
* @param nbBits Number of quantization bits.
* @param span Fixed output span of the quantizers.
*/
void insertQuantizers(std::shared_ptr<GraphView> graphView, size_t nbBits, float span);
/**
* @brief Given a GraphView with parameters properly initialized and some calibration data,
* insert the FixedQ quantizer nodes, and adjust their output spans.
* @param graphView The GraphView containing the graph to quantize.
* @param nbBits Number of quantization bits.
* @param calibrationData Calibration data used to adjust the spans.
* @param scale Multiplicative constant applied to the spans.
*/
void insertAndInitQuantizers(std::shared_ptr<GraphView> graphView, size_t nbBits, std::shared_ptr<Tensor> calibrationData, float scale);
/**
* @brief Developement and test routine.
* @param graphView The GraphView under test.
*/
void devQAT(std::shared_ptr<GraphView> graphView);
}
}
#endif /* AIDGE_QUANTIZATION_QAT_FIXEDQ_H_ */
+ 44
0
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_QUANTIZATION_QAT_LSQ_H_
#define AIDGE_QUANTIZATION_QAT_LSQ_H_
#include "aidge/graph/Node.hpp"
#include "aidge/graph/GraphView.hpp"
#include "aidge/data/Tensor.hpp"
namespace Aidge {
namespace QuantLSQ {
/**
* @brief Insert the LSQ quantizer nodes in a given GraphView
* @param graphView The GraphView containing the graph to quantize.
* @param nbBits Number of quantization bits.
* @param span Fixed output span of the quantizers.
*/
void insertQuantizers(std::shared_ptr<GraphView> graphView, size_t nbBits, float step_size);
/**
* @brief Given a GraphView with parameters properly initialized and some calibration data,
* insert the LSQ quantizer nodes, and adjust their step-sizes.
* @param graphView The GraphView containing the graph to quantize.
* @param nbBits Number of quantization bits.
* @param calibrationData Calibration data used to adjust the spans.
* @param scale Multiplicative constant applied to the spans.
*/
void insertAndInitQuantizers(std::shared_ptr<GraphView> graphView, size_t nbBits, std::shared_ptr<Tensor> calibrationData);
}
}
#endif /* AIDGE_QUANTIZATION_QAT_LSQ_H_ */
Loading