Skip to content
Snippets Groups Projects
Commit 8ec15e6e authored by Maxence Naud's avatar Maxence Naud
Browse files

update according to core changes

parent 81d562fa
No related branches found
No related tags found
2 merge requests!14version 0.1.1,!13update according to core changes
......@@ -71,7 +71,7 @@ class ProducerCPP(ExportNode):
def __init__(self, node):
super().__init__(node)
self.constant = self.operator.get_attr("Constant")
self.constant = self.operator.attr.constant
self.values = np.array(self.operator.get_output(0))
if len(self.values.shape) == 4:
......@@ -130,7 +130,7 @@ class ReLUCPP(ExportNode):
list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "activation_forward.jinja"),
name=self.name,
input_name=self.inputs[0].name(),
input_name=self.inputs[0].name() if self.inputs[0] else self.name + "_input",
output_name=self.name
))
return list_actions
......@@ -141,16 +141,16 @@ class ConvCPP(ExportNode):
def __init__(self, node):
super().__init__(node)
self.kernel = node.get_operator().get_attr("KernelDims")
self.stride = node.get_operator().get_attr("StrideDims")
self.dilation = node.get_operator().get_attr("DilationDims")
self.kernel = node.get_operator().attr.kernel_dims
self.stride = node.get_operator().attr.stride_dims
self.dilation = node.get_operator().attr.dilation_dims
# No padding with Conv
# Use PaddedConv to add padding attribute
self.padding = [0, 0]
self.nb_channels = node.get_operator().get_attr("InChannels")
self.nb_outputs = node.get_operator().get_attr("OutChannels")
self.nb_channels = node.get_operator().in_channels()
self.nb_outputs = node.get_operator().out_channels()
if len(self.inputs_dims[0]) == 4:
# if dims == [batch, nb_channels, height, width]
......@@ -196,7 +196,7 @@ class ConvCPP(ExportNode):
list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "convolution_forward.jinja"),
name=self.name,
input_name=self.inputs[0].name(),
input_name=self.inputs[0].name() if self.inputs[0] else self.name + "_input",
output_name=self.name,
weights_name=self.inputs[1].name(),
biases_name=self.inputs[2].name()
......@@ -211,11 +211,11 @@ class PaddedConvCPP(ConvCPP):
for n in self.operator.get_micro_graph().get_nodes():
if n.type() == "Pad":
self.padding = n.get_operator().get_attr("BeginEndBorders")
self.padding = n.get_operator().attr.begin_end_borders
if n.type() == "Conv":
self.kernel = n.get_operator().get_attr("KernelDims")
self.stride = n.get_operator().get_attr("StrideDims")
self.dilation = n.get_operator().get_attr("DilationDims")
self.kernel = n.get_operator().attr.kernel_dims
self.stride = n.get_operator().attr.stride_dims
self.dilation = n.get_operator().attr.dilation_dims
if len(self.inputs_dims[0]) == 4:
# if dims == [batch, nb_channels, height, width]
......@@ -256,8 +256,8 @@ class AddCPP(ExportNode):
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja"),
name=self.name,
inputs1_name=self.parents[0].name(),
inputs2_name=self.parents[1].name(),
inputs1_name=self.parents[0].name() if self.parents[0] else self.name + "_input1",
inputs2_name=self.parents[1].name() if self.parents[1] else self.name + "_input2",
output_name=self.name
))
return list_actions
......@@ -289,8 +289,8 @@ class SubCPP(ExportNode):
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja"),
name=self.name,
inputs1_name=self.inputs[0].name(),
inputs2_name=self.inputs[1].name(),
inputs1_name=self.inputs[0].name() if self.inputs[0] else self.name + "_input1",
inputs2_name=self.inputs[1].name() if self.inputs[1] else self.name + "_input2",
output_name=self.name
))
return list_actions
......@@ -300,8 +300,8 @@ class MaxPoolCPP(ExportNode):
def __init__(self, node):
super().__init__(node)
self.kernel = node.get_operator().get_attr("KernelDims")
self.stride = node.get_operator().get_attr("StrideDims")
self.kernel = node.get_operator().attr.kernel_dims
self.stride = node.get_operator().attr.stride_dims
# No padding with MaxPooling
# Use PaddedMaxPooling to add padding attribute
......@@ -347,7 +347,7 @@ class MaxPoolCPP(ExportNode):
list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja"),
name=self.name,
input_name=self.inputs[0].name(),
input_name=self.inputs[0].name() if self.inputs[0] else self.name + "_input",
output_name=self.name
))
return list_actions
......@@ -400,11 +400,10 @@ class FcCPP(ExportNode):
def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "fullyconnected_forward.jinja"),
name=self.name,
inputs_name=self.inputs[0].name(),
inputs_name= self.inputs[0].name() if (self.inputs[0] is not None) else self.name + '_input',
weights_name=self.inputs[1].name(),
biases_name=self.inputs[2].name(),
outputs_name=self.name
......
......@@ -17,18 +17,18 @@ def numpy_dtype2ctype(dtype):
# Add more dtype mappings as needed
else:
raise ValueError(f"Unsupported {dtype} dtype")
def aidge_datatype2ctype(datatype):
if datatype == aidge_core.DataType.Int8:
if datatype == aidge_core.dtype.int8:
return "int8_t"
elif datatype == aidge_core.DataType.Int32:
elif datatype == aidge_core.dtype.int32:
return "int32_t"
elif datatype == aidge_core.DataType.Int64:
elif datatype == aidge_core.dtype.int64:
return "int64_t"
elif datatype == aidge_core.DataType.Float32:
elif datatype == aidge_core.dtype.float32:
return "float"
elif datatype == aidge_core.DataType.Float64:
elif datatype == aidge_core.dtype.float64:
return "double"
# Add more dtype mappings as needed
else:
......
%% Cell type:markdown id: tags:
# Export a MNIST model to a CPP standalone project
%% Cell type:code id: tags:
``` python
%pip install requests numpy ipywidgets ipycanvas
```
%% Cell type:markdown id: tags:
## Download the model
%% Cell type:code id: tags:
``` python
import os
import requests
```
%% Cell type:code id: tags:
``` python
# Download onnx file if it has not been done before
if not os.path.isfile("./lenet_mnist.onnx"):
response = requests.get("https://huggingface.co/vtemplier/LeNet_MNIST/resolve/main/lenet_mnist.onnx?download=true")
if response.status_code == 200:
with open("lenet_mnist.onnx", 'wb') as f:
f.write(response.content)
print("ONNX model downloaded successfully.")
else:
print("Failed to download ONNX model. Status code:", response.status_code)
```
%% Cell type:markdown id: tags:
## Load the model in Aidge and manipulate it
%% Cell type:code id: tags:
``` python
import aidge_core
import aidge_backend_cpu
import aidge_onnx
import aidge_export_cpp
```
%% Cell type:code id: tags:
``` python
model = aidge_onnx.load_onnx("lenet_mnist.onnx")
```
%% Cell type:code id: tags:
``` python
# Remove Flatten node, useless in the CPP export
aidge_core.remove_flatten(model)
# Freeze the model by setting constant to parameters producers
for node in model.get_nodes():
if node.type() == "Producer":
node.get_operator().set_attr("Constant", True)
# Create Producer Node for the Graph
input_node = aidge_core.Producer([1, 1, 28, 28], "input")
input_node.add_child(model)
model.add(input_node)
# Configuration for the model + forward dimensions
model.compile("cpu", aidge_core.DataType.Float32)
model.compile("cpu", aidge_core.dtype.float32)
```
%% Cell type:code id: tags:
``` python
# Generate scheduling of the model
scheduler = aidge_core.SequentialScheduler(model)
scheduler.generate_scheduling()
```
%% Cell type:code id: tags:
``` python
model.save("test")
```
%% Cell type:markdown id: tags:
## Export the model
%% Cell type:code id: tags:
``` python
aidge_export_cpp.export("lenet_export_fp32", model, scheduler)
```
%% Cell type:markdown id: tags:
### Draw your own number
%% Cell type:code id: tags:
``` python
from ipywidgets import HBox, VBox, Button, Layout
from ipycanvas import RoughCanvas, hold_canvas
img_name = "my_number.png"
canvas = RoughCanvas(width=28, height=28, sync_image_data=True)
button_gen = Button(description="Generate PNG")
button_clear = Button(description="Clear")
drawing = False
position = None
shape = []
def on_erase_button_clicked(b):
canvas.clear()
def on_generate_button_clicked(b):
try:
canvas.to_file(img_name)
print(f"Image generated to {img_name} !")
except:
print("Draw a number before generating the image.")
button_clear.on_click(on_erase_button_clicked)
button_gen.on_click(on_generate_button_clicked)
def on_mouse_down(x, y):
global drawing
global position
global shape
drawing = True
position = (x, y)
shape = [position]
def on_mouse_move(x, y):
global drawing
global position
global shape
if not drawing:
return
with hold_canvas():
canvas.stroke_line(position[0], position[1], x, y)
position = (x, y)
shape.append(position)
def on_mouse_up(x, y):
global drawing
global position
global shape
drawing = False
with hold_canvas():
canvas.stroke_line(position[0], position[1], x, y)
shape = []
canvas.on_mouse_down(on_mouse_down)
canvas.on_mouse_move(on_mouse_move)
canvas.on_mouse_up(on_mouse_up)
canvas.stroke_style = "#000000"
VBox((canvas, HBox((button_gen, button_clear))),
layout=Layout(height='auto', width="300px"))
```
%% Cell type:markdown id: tags:
### Generate inputs for testing the model from your drawing
%% Cell type:code id: tags:
``` python
try:
number_np = canvas.get_image_data()
# We got a numpy array with the shape of (28,28,4)
# Transform it to (28,28)
x = number_np[:, :, 3].astype("float32")
# Convert from [0, 255] to [0, 1] and export it
aidge_export_cpp.generate_input_file(export_folder="lenet_export_fp32",
array_name="inputs",
array=x / 255)
except:
print("Please draw a number in the previous cell before running this one.")
```
%% Cell type:markdown id: tags:
### Compile the export and test it
%% Cell type:code id: tags:
``` python
!cd lenet_export_fp32 && make
```
%% Cell type:code id: tags:
``` python
!./lenet_export_fp32/bin/run_export
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment