GithubHelp home page GithubHelp logo

f0uriest / keras2c Goto Github PK

View Code? Open in Web Editor NEW
86.0 5.0 33.0 7.39 MB

A simple library to deploy Keras neural networks in pure C for realtime applications

License: GNU Lesser General Public License v3.0

Jupyter Notebook 3.84% C 56.44% Python 39.56% Makefile 0.16%
keras tensorflow machine-learning real-time control-systems neural-network c cpp keras-to-c convert-keras convert-tensorflow

keras2c's Introduction

keras2c

Build Status Code Coverage

License: LGPLv3 Please Cite Keras2c!

keras2c is a library for deploying keras neural networks in C99, using only standard libraries. It is designed to be as simple as possible for real time applications.

Quickstart

After cloning the repo, install the necessary packages with pip install -r requirements.txt.

keras2c can be used from the command line:

python -m keras2c [-h] [-m] [-t] model_path function_name

A library for converting the forward pass (inference) part of a keras model to
    a C function

positional arguments:
  model_path         File path to saved keras .h5 model file
  function_name      What to name the resulting C function

optional arguments:
  -h, --help         show this help message and exit
  -m, --malloc       Use dynamic memory for large arrays. Weights will be
                     saved to .csv files that will be loaded at runtime
  -t , --num_tests   Number of tests to generate. Default is 10

It can also be used with a python environment in the following manner:

from keras2c import k2c
k2c(model, function_name, malloc=False, num_tests=10, verbose=True)

For more information, see Installation and Usage

Supported Layers

  • Core Layers: Dense, Activation, Dropout, Flatten, Input, Reshape, Permute, RepeatVector, ActivityRegularization, SpatialDropout1D, SpatialDropout2D, SpatialDropout3D
  • Convolution Layers: Conv1D, Conv2D, Conv3D, Cropping1D, Cropping2D, Cropping3D, UpSampling1D, UpSampling2D, UpSampling3D, ZeroPadding1D, ZeroPadding2D, ZeroPadding3D
  • Pooling Layers: MaxPooling1D, MaxPooling2D, AveragePooling1D, AveragePooling2D, GlobalMaxPooling1D, GlobalAveragePooling1D, GlobalMaxPooling2D, GlobalAveragePooling2D, GlobalMaxPooling3D,GlobalAveragePooling3D
  • Recurrent Layers: SimpleRNN, GRU, LSTM, SimpleRNNCell, GRUCell, LSTMCell
  • Embedding Layers: Embedding
  • Merge Layers: Add, Subtract, Multiply, Average, Maximum, Minimum, Concatenate, Dot
  • Advanced Activation Layers: LeakyReLU, PReLU, ELU, ThresholdedReLU, Softmax, ReLU
  • Normalization Layers: BatchNormalization
  • Noise Layers: GaussianNoise, GaussianDropout, AlphaDropout
  • Layer Wrappers: TimeDistributed, Bidirectional

ToDo

  • Core Layers: Lambda, Masking
  • Convolution Layers: SeparableConv1D, SeparableConv2D, DepthwiseConv2D, Conv2DTranspose, Conv3DTranspose
  • Pooling Layers: MaxPooling3D, AveragePooling3D
  • Locally Connected Layers: LocallyConnected1D, LocallyConnected2D
  • Recurrent Layers: ConvLSTM2D, ConvLSTM2DCell
  • Merge Layers: Broadcasting merge between different sizes
  • Misc: models made from submodels

Contribute

License

The project is licensed under the LGPLv3 license.

keras2c's People

Contributors

f0uriest avatar roboticarm2000 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

keras2c's Issues

k2c_maxpool2d in time_distributed gives segmentation fault

The code generated by keras2c is the following:

for (size_t i = 0; i < time_distributed_1_timesteps; ++i)
{
    max_pooling2d_timeslice_input.array = &time_distributed_output.array[i * time_distributed_1_in_offset];
    max_pooling2d_timeslice_output.array = &time_distributed_1_output.array[i * time_distributed_1_out_offset];
    k2c_maxpool2d(&max_pooling2d_timeslice_output, &max_pooling2d_timeslice_input, max_pooling2d_pool_size,
					    max_pooling2d_stride);
}

It compiles fine, but when in execution, it raises an error (SIGSEGV) when calling k2c_maxpool2d()

Random behaviour of generated .c inference file

Hello. I am creating a simple network of around 10 layers composed of convolutions and max pooling, ending with a dense layer. The input is an array of a few thousand values, the output is an array of a small number of values (e.g. 10).

I can convert the network successfully to .C using this library. But when inferring the C files, the code behaves randomly. Sometimes it gives the expected 10 value result, sometimes it gives a Segmentation fault (core dumped) error. If I run the resulting executable consecutively, it might produce an output, or it might give the segmentation error.

Any ideas please? I can post the code if needed.. Thank you.

Error undefined reference to `lstm(k2c_tensor*, k2c_tensor*)'

Hello,

I am trying to convert a LSTM NN to C. I was able to generate the C files using your library but when I try to run the example in C I get the error "lstm(k2c_tensor*, k2c_tensor*)". Do you know what can be the cause of this?
I attached the code.
Thank you

#include <stdio.h>
#include <math.h>
#include <time.h>
#include "./keras2c/include/k2c_include.h"
#include "./lstm.h"

float maxabs(k2c_tensor *tensor1, k2c_tensor *tensor2);
struct timeval GetTimeStamp();

float test1_lstm_input_input_array[12] = {
    -1.13245840e+00f,
    -1.88968293e+00f,
    -1.01585267e-01f,
    -5.98125538e-01f,
    -1.60964425e+00f,
    +1.75511004e+00f,
    -1.52169081e+00f,
    -1.57987595e+00f,
    +1.23946883e+00f,
    -1.41191308e+00f,
    +8.65569771e-01f,
    +7.68581566e-01f,
};
k2c_tensor test1_lstm_input_input = {&test1_lstm_input_input_array[0], 2, 12, {4, 3, 1, 1, 1}};
float keras_dense_test1_array[1] = {
    -5.31204462e-01f,
};
k2c_tensor keras_dense_test1 = {&keras_dense_test1_array[0], 1, 1, {1, 1, 1, 1, 1}};
float c_dense_test1_array[1] = {0};
k2c_tensor c_dense_test1 = {&c_dense_test1_array[0], 1, 1, {1, 1, 1, 1, 1}};
float test2_lstm_input_input_array[12] = {
    +3.94249042e-01f,
    -4.07409747e-01f,
    -6.77222531e-01f,
    +1.97063872e+00f,
    +1.23045506e+00f,
    +1.39234612e+00f,
    -8.36423398e-01f,
    -3.03802024e-01f,
    -1.03085725e+00f,
    +1.14633289e+00f,
    +7.20393857e-01f,
    -1.17798856e+00f,
};
k2c_tensor test2_lstm_input_input = {&test2_lstm_input_input_array[0], 2, 12, {4, 3, 1, 1, 1}};
float keras_dense_test2_array[1] = {
    +3.58893424e-01f,
};
k2c_tensor keras_dense_test2 = {&keras_dense_test2_array[0], 1, 1, {1, 1, 1, 1, 1}};
float c_dense_test2_array[1] = {0};
k2c_tensor c_dense_test2 = {&c_dense_test2_array[0], 1, 1, {1, 1, 1, 1, 1}};
float test3_lstm_input_input_array[12] = {
    -4.65610290e-01f,
    -1.75561958e+00f,
    +1.29821420e+00f,
    -4.74955731e-01f,
    -1.47081012e+00f,
    +1.50551550e+00f,
    +4.28652033e-02f,
    -7.00394754e-01f,
    -1.58612456e+00f,
    +3.65025042e-01f,
    +1.90088424e+00f,
    -1.15637390e-01f,
};
k2c_tensor test3_lstm_input_input = {&test3_lstm_input_input_array[0], 2, 12, {4, 3, 1, 1, 1}};
float keras_dense_test3_array[1] = {
    -2.32015252e-02f,
};
k2c_tensor keras_dense_test3 = {&keras_dense_test3_array[0], 1, 1, {1, 1, 1, 1, 1}};
float c_dense_test3_array[1] = {0};
k2c_tensor c_dense_test3 = {&c_dense_test3_array[0], 1, 1, {1, 1, 1, 1, 1}};
float test4_lstm_input_input_array[12] = {
    +7.78019686e-01f,
    +1.14394216e+00f,
    +1.47736387e+00f,
    +1.13235781e+00f,
    -8.92344912e-03f,
    -1.03233765e-01f,
    -1.40811364e+00f,
    -7.14377063e-01f,
    +1.53193782e+00f,
    -1.51097806e-01f,
    +1.73710253e-01f,
    -1.31863513e+00f,
};
k2c_tensor test4_lstm_input_input = {&test4_lstm_input_input_array[0], 2, 12, {4, 3, 1, 1, 1}};
float keras_dense_test4_array[1] = {
    +5.08163869e-03f,
};
k2c_tensor keras_dense_test4 = {&keras_dense_test4_array[0], 1, 1, {1, 1, 1, 1, 1}};
float c_dense_test4_array[1] = {0};
k2c_tensor c_dense_test4 = {&c_dense_test4_array[0], 1, 1, {1, 1, 1, 1, 1}};
float test5_lstm_input_input_array[12] = {
    +1.74445294e+00f,
    +3.46498525e-01f,
    +1.30536050e+00f,
    +9.16105772e-01f,
    -9.29711491e-01f,
    -5.63974734e-01f,
    +1.72561155e+00f,
    +1.68685380e+00f,
    -4.14265337e-01f,
    +4.03739047e-01f,
    -5.95306724e-01f,
    -5.11684715e-01f,
};
k2c_tensor test5_lstm_input_input = {&test5_lstm_input_input_array[0], 2, 12, {4, 3, 1, 1, 1}};
float keras_dense_test5_array[1] = {
    +8.75042528e-02f,
};
k2c_tensor keras_dense_test5 = {&keras_dense_test5_array[0], 1, 1, {1, 1, 1, 1, 1}};
float c_dense_test5_array[1] = {0};
k2c_tensor c_dense_test5 = {&c_dense_test5_array[0], 1, 1, {1, 1, 1, 1, 1}};

int main()
{
    float errors[5];
    size_t num_tests = 5;
    size_t num_outputs = 1;
    lstm_initialize();
    clock_t t0 = clock();
    lstm(&test1_lstm_input_input, &c_dense_test1);
    lstm(&test2_lstm_input_input, &c_dense_test2);
    lstm(&test3_lstm_input_input, &c_dense_test3);
    lstm(&test4_lstm_input_input, &c_dense_test4);
    lstm(&test5_lstm_input_input, &c_dense_test5);

    clock_t t1 = clock();
    printf("Average time over 5 tests: %e s \n",
           ((double)t1 - t0) / (double)CLOCKS_PER_SEC / (double)5);
    errors[0] = maxabs(&keras_dense_test1, &c_dense_test1);
    errors[1] = maxabs(&keras_dense_test2, &c_dense_test2);
    errors[2] = maxabs(&keras_dense_test3, &c_dense_test3);
    errors[3] = maxabs(&keras_dense_test4, &c_dense_test4);
    errors[4] = maxabs(&keras_dense_test5, &c_dense_test5);
    float maxerror = errors[0];
    for (size_t i = 1; i < num_tests * num_outputs; i++)
    {
        if (errors[i] > maxerror)
        {
            maxerror = errors[i];
        }
    }
    printf("Max absolute error for 5 tests: %e \n", maxerror);
    lstm_terminate();
    if (maxerror > 1e-05)
    {
        return 1;
    }
    return 0;
}

float maxabs(k2c_tensor *tensor1, k2c_tensor *tensor2)
{

    float x = 0;

    float y = 0;

    for (size_t i = 0; i < tensor1->numel; i++)
    {

        y = fabsf(tensor1->array[i] - tensor2->array[i]);
        if (y > x)
        {
            x = y;
        }
    }
    return x;
}

float vs double

Hello,
Because it is possible to use keras in python with double precision keras.backend.set_floatx('float64') , will you insert a option to create model.c, model.h and model_test.c with double precision ?

Thank you,
Julien

Multiple definition of 'k2c_linear' and others when compiling test

I am trying to compile the example test suite. I followed the installation instructions, and I can convert model.h5 (in the example folder) to example.c and example.h:

All checks passed
Gathering Weights
Writing layer  input_1:0
Writing layer  dense_1
Writing layer  dense_2
Writing layer  lstm_1
Writing layer  dense_3
Formatted  /home/ryley/WDK/ML/foam/keras2c/example.h
Formatted  /home/ryley/WDK/ML/foam/keras2c/example.c
Writing tests
/home/ryley/anaconda3/envs/keras2c/lib/python3.9/site-packages/keras/engine/training.py:2470: UserWarning: `Model.state_updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
  warnings.warn('`Model.state_updates` will be removed in a future version. '
Formatted  /home/ryley/WDK/ML/foam/keras2c/example_test_suite.c
Done 
C code is in 'example.c' with header file 'example.h' 
Tests are in 'example_test_suite.c' 

compiling with the following command

gcc -std=c99 -I./include/ -o example_test example.c example_test_suite.c -L./include/ -l:libkeras2c.a -lm

Gives the errors:

/usr/bin/ld: /tmp/ccypuWyQ.o:(.bss+0x0): multiple definition of `k2c_linear'; /tmp/ccR5zelS.o:(.bss+0x0): first defined here
/usr/bin/ld: /tmp/ccypuWyQ.o:(.bss+0x8): multiple definition of `k2c_exponential'; /tmp/ccR5zelS.o:(.bss+0x8): first defined here
/usr/bin/ld: /tmp/ccypuWyQ.o:(.bss+0x10): multiple definition of `k2c_relu'; /tmp/ccR5zelS.o:(.bss+0x10): first defined here
/usr/bin/ld: /tmp/ccypuWyQ.o:(.bss+0x18): multiple definition of `k2c_hard_sigmoid'; /tmp/ccR5zelS.o:(.bss+0x18): first defined here
/usr/bin/ld: /tmp/ccypuWyQ.o:(.bss+0x20): multiple definition of `k2c_tanh'; /tmp/ccR5zelS.o:(.bss+0x20): first defined here
/usr/bin/ld: /tmp/ccypuWyQ.o:(.bss+0x28): multiple definition of `k2c_sigmoid'; /tmp/ccR5zelS.o:(.bss+0x28): first defined here
/usr/bin/ld: /tmp/ccypuWyQ.o:(.bss+0x30): multiple definition of `k2c_softmax'; /tmp/ccR5zelS.o:(.bss+0x30): first defined here
/usr/bin/ld: /tmp/ccypuWyQ.o:(.bss+0x38): multiple definition of `k2c_softplus'; /tmp/ccR5zelS.o:(.bss+0x38): first defined here
/usr/bin/ld: /tmp/ccypuWyQ.o:(.bss+0x40): multiple definition of `k2c_softsign'; /tmp/ccR5zelS.o:(.bss+0x40): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_core_layers.o):(.bss+0x0): multiple definition of `k2c_softsign'; /tmp/ccR5zelS.o:(.bss+0x40): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_core_layers.o):(.bss+0x8): multiple definition of `k2c_softplus'; /tmp/ccR5zelS.o:(.bss+0x38): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_core_layers.o):(.bss+0x10): multiple definition of `k2c_softmax'; /tmp/ccR5zelS.o:(.bss+0x30): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_core_layers.o):(.bss+0x18): multiple definition of `k2c_sigmoid'; /tmp/ccR5zelS.o:(.bss+0x28): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_core_layers.o):(.bss+0x20): multiple definition of `k2c_tanh'; /tmp/ccR5zelS.o:(.bss+0x20): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_core_layers.o):(.bss+0x28): multiple definition of `k2c_hard_sigmoid'; /tmp/ccR5zelS.o:(.bss+0x18): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_core_layers.o):(.bss+0x30): multiple definition of `k2c_relu'; /tmp/ccR5zelS.o:(.bss+0x10): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_core_layers.o):(.bss+0x38): multiple definition of `k2c_exponential'; /tmp/ccR5zelS.o:(.bss+0x8): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_core_layers.o):(.bss+0x40): multiple definition of `k2c_linear'; /tmp/ccR5zelS.o:(.bss+0x0): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_helper_functions.o):(.bss+0x0): multiple definition of `k2c_softsign'; /tmp/ccR5zelS.o:(.bss+0x40): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_helper_functions.o):(.bss+0x8): multiple definition of `k2c_softplus'; /tmp/ccR5zelS.o:(.bss+0x38): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_helper_functions.o):(.bss+0x10): multiple definition of `k2c_softmax'; /tmp/ccR5zelS.o:(.bss+0x30): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_helper_functions.o):(.bss+0x18): multiple definition of `k2c_sigmoid'; /tmp/ccR5zelS.o:(.bss+0x28): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_helper_functions.o):(.bss+0x20): multiple definition of `k2c_tanh'; /tmp/ccR5zelS.o:(.bss+0x20): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_helper_functions.o):(.bss+0x28): multiple definition of `k2c_hard_sigmoid'; /tmp/ccR5zelS.o:(.bss+0x18): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_helper_functions.o):(.bss+0x30): multiple definition of `k2c_relu'; /tmp/ccR5zelS.o:(.bss+0x10): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_helper_functions.o):(.bss+0x38): multiple definition of `k2c_exponential'; /tmp/ccR5zelS.o:(.bss+0x8): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_helper_functions.o):(.bss+0x40): multiple definition of `k2c_linear'; /tmp/ccR5zelS.o:(.bss+0x0): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_recurrent_layers.o):(.bss+0x0): multiple definition of `k2c_softsign'; /tmp/ccR5zelS.o:(.bss+0x40): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_recurrent_layers.o):(.bss+0x8): multiple definition of `k2c_softplus'; /tmp/ccR5zelS.o:(.bss+0x38): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_recurrent_layers.o):(.bss+0x10): multiple definition of `k2c_softmax'; /tmp/ccR5zelS.o:(.bss+0x30): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_recurrent_layers.o):(.bss+0x18): multiple definition of `k2c_sigmoid'; /tmp/ccR5zelS.o:(.bss+0x28): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_recurrent_layers.o):(.bss+0x20): multiple definition of `k2c_tanh'; /tmp/ccR5zelS.o:(.bss+0x20): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_recurrent_layers.o):(.bss+0x28): multiple definition of `k2c_hard_sigmoid'; /tmp/ccR5zelS.o:(.bss+0x18): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_recurrent_layers.o):(.bss+0x30): multiple definition of `k2c_relu'; /tmp/ccR5zelS.o:(.bss+0x10): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_recurrent_layers.o):(.bss+0x38): multiple definition of `k2c_exponential'; /tmp/ccR5zelS.o:(.bss+0x8): first defined here
/usr/bin/ld: ./include//libkeras2c.a(k2c_recurrent_layers.o):(.bss+0x40): multiple definition of `k2c_linear'; /tmp/ccR5zelS.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status

trying to match tf.nn.conv2d vs keras2c

I've been having issues matching the output of conv2d from keras to the output of keras2c. I've been trying to unit test the k2c_conv2d vs the output of tf.nn.conv2d.

Below is the code that I used to generate my "truth" using tf.nn.conv2d. I have an 80x80 chip of ones convolved with a 7x7 kernel of ones. The script test_conv2d.py produces two outputs. The first output is the result of the convolution using a stride of 1 and the second output is the result of the convolution using a stride of 2. In the first case, the output of the first 3 rows is not 49. This makes sense since the mask goes outside the image and with padding set to 'same', the assumed value outside the image is assumed zero. In the second case, the first row and the last two rows is not 49 as expected.

# test_conv2d.py
import numpy as np
import tensorflow as tf
x_in = np.ones((1,80,80,1),dtype='float32')
kernel_in = np.ones((7,7,1,1),dtype='float32')
x = tf.constant(x_in, dtype=tf.float32)
kernel = tf.constant(kernel_in, dtype=tf.float32)
result = tf.nn.conv2d(x, kernel, strides=[1, 1], padding='SAME')
arr = result[0,:,:,0]
np.save('conv2d_example_s1.npy',arr.numpy())
result2 = tf.nn.conv2d(x, kernel, strides=[2, 2], padding='SAME')
arr2 = result2[0,:,:,0]
np.save('conv2d_example_s2.npy',arr2.numpy())

I'm assuming that in order to match with keras2c, I need to pad the image to an 86x86 (by adding 3 rows and columns on each side set to zero), then convolve the padded image to generate an output image of 80x80 for stride 1 and 40x40 for stride 2.

Below is the C code that I used to perform the convolution in k2c.

/* test2d.c */
#include "k2c_include.h"
#include <stdio.h>

#define num_channels  2
float input_buffer[80*80] = {0};
k2c_tensor input = {&input_buffer[0],num_channels,80*80,{ 80,80, 1, 1, 1}};

float pad_buffer[86*86]= {0};
k2c_tensor pad = {&pad_buffer[0],num_channels,86*86,{86,86,1,1,1}};

float output_buffer[86*86] = {0};
k2c_tensor output = {&output_buffer[0],num_channels,80*80,{ 80,80, 1, 1, 1}};
k2c_tensor output2 = {&output_buffer[0],num_channels,40*40,{ 40,40, 1, 1, 1}};


float kernel_buffer[7*7] = {0};
k2c_tensor kernel = {&kernel_buffer[0],num_channels,7*7,{ 7,7, 1, 1, 1}};

float bias_buffer = 0;
k2c_tensor bias = {&bias_buffer,num_channels,1,{ 1,1, 1, 1, 1}};


size_t stride[num_channels] = {1,1};
size_t dilation[num_channels] = {0};
size_t pad_values[4] = {3,3,3,3};

void print_tensor(k2c_tensor* output)
{
  int k=0;
  for (int i=0;i<output->shape[0];++i) {
    for (int j=0;j<output->shape[1];++j,++k) {
      printf("%.9f ",output->array[k]);
    }
    printf("\n");
  }

}

int main(int argc, char** argv)
{
  if (argc >= 3) {
    stride[0] = atoi(argv[1]);
    stride[1] = atoi(argv[2]);
  }
  
  for (int i=0;i<80*80;++i) {
      input_buffer[i] = 1;
  }
  for (int i=0;i<7*7;++i) {
    kernel_buffer[i] = 1;
  }
  /**
 * 2D (spatial) Padding.
 *
 * :param output: tensor to store padded output data.
 * :param input: tensor to pad.
 * :param fill: value to fill in padded areas.
 * :param pad: array[4] of how many rows/cols to pad. Order is {before dim 1, after dim 1, before dim 2, after dim 2}.
 */
  k2c_pad2d(&pad, &input, 0.0f, pad_values);

  //  print_tensor(&pad);
  //return 0;
  
  if (stride[0] == 1) {
    k2c_conv2d(&output, &pad, &kernel,
               &bias, stride, dilation,
               k2c_linear);
    print_tensor(&output);
  } else {
    k2c_conv2d(&output2, &pad, &kernel,
               &bias, stride, dilation,
               k2c_linear);
    print_tensor(&output2);
  }


  return 0;
}

I generated the resulting chips using these commands:

./test2d.exe 1 1 > d1.txt && ./test2d.exe 2 2 > d2.txt

Then used the following script to compare the output from tensorflow vs k2c:

# show_pair.py
import numpy as np
import matplotlib.pyplot as plt

def show_pair():
    d1 = np.loadtxt('d1.txt')
    d2 = np.loadtxt('d2.txt')

    p1 = np.load('conv2d_example_s1.npy')
    p2 = np.load('conv2d_example_s2.npy')

    plt.figure()
    plt.subplot(2,2,1); plt.matshow(d1,fignum=False); plt.title('k2c stride 1')
    plt.subplot(2,2,2); plt.matshow(p1,fignum=False); plt.title('tf stride 1')
    plt.subplot(2,2,3); plt.matshow(d2,fignum=False); plt.title('k2c stride 2')
    plt.subplot(2,2,4); plt.matshow(p2,fignum=False); plt.title('tf stride 2')

    plt.show()

if __name__ == '__main__':
    show_pair()

Attached is the image that I generated.
example_output

First, notice there is not gradient in the output of k2c. Second, pixel (2,2) is the first value on the k2c convolution with stride 2 with value 49 vs pixel(1,1) from the output of tf with stride 2.

I maybe simulating the tf.nn.conv2d incorrectly in C. Feedback in how to do it correctly is welcomed. But I think the shift of the stride is still different.

Your help will be greatly appreciated

Warnings and seg fault related to `k2c_LeakyReLU`

gcc -std=c99 -I./include/ -c -o fire_test.o fire_model.c -L./include/ -l:libkeras2c.a -lm
fire_model.c: In function ‘fire_model’:
fire_model.c:54402:15: warning: passing argument 1 of ‘k2c_LeakyReLU’ from incompatible pointer type [-Wincompatible-pointer-types]
54402 | k2c_LeakyReLU(&conv2d_output.array,&conv2d_output.numel,leaky_re_lu_alpha);
      |               ^~~~~~~~~~~~~~~~~~~~
      |               |
      |               float **
In file included from fire_model.c:3:
./include/k2c_include.h:37:28: note: expected ‘float *’ but argument is of type ‘float **’
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                    ~~~~~~~~^
fire_model.c:54402:36: warning: passing argument 2 of ‘k2c_LeakyReLU’ makes integer from pointer without a cast [-Wint-conversion]
54402 | k2c_LeakyReLU(&conv2d_output.array,&conv2d_output.numel,leaky_re_lu_alpha);
      |                                    ^~~~~~~~~~~~~~~~~~~~
      |                                    |
      |                                    size_t * {aka long unsigned int *}
In file included from fire_model.c:3:
./include/k2c_include.h:37:44: note: expected ‘size_t’ {aka ‘const long unsigned int’} but argument is of type ‘size_t *’ {aka ‘long unsigned int *’}
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                               ~~~~~~~~~~~~~^~~~
fire_model.c:54416:15: warning: passing argument 1 of ‘k2c_LeakyReLU’ from incompatible pointer type [-Wincompatible-pointer-types]
54416 | k2c_LeakyReLU(&conv2d_1_output.array,&conv2d_1_output.numel,leaky_re_lu_1_alpha);
      |               ^~~~~~~~~~~~~~~~~~~~~~
      |               |
      |               float **
In file included from fire_model.c:3:
./include/k2c_include.h:37:28: note: expected ‘float *’ but argument is of type ‘float **’
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                    ~~~~~~~~^
fire_model.c:54416:38: warning: passing argument 2 of ‘k2c_LeakyReLU’ makes integer from pointer without a cast [-Wint-conversion]
54416 | k2c_LeakyReLU(&conv2d_1_output.array,&conv2d_1_output.numel,leaky_re_lu_1_alpha);
      |                                      ^~~~~~~~~~~~~~~~~~~~~~
      |                                      |
      |                                      size_t * {aka long unsigned int *}
In file included from fire_model.c:3:
./include/k2c_include.h:37:44: note: expected ‘size_t’ {aka ‘const long unsigned int’} but argument is of type ‘size_t *’ {aka ‘long unsigned int *’}
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                               ~~~~~~~~~~~~~^~~~
fire_model.c:54430:15: warning: passing argument 1 of ‘k2c_LeakyReLU’ from incompatible pointer type [-Wincompatible-pointer-types]
54430 | k2c_LeakyReLU(&conv2d_2_output.array,&conv2d_2_output.numel,leaky_re_lu_2_alpha);
      |               ^~~~~~~~~~~~~~~~~~~~~~
      |               |
      |               float **
In file included from fire_model.c:3:
./include/k2c_include.h:37:28: note: expected ‘float *’ but argument is of type ‘float **’
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                    ~~~~~~~~^
fire_model.c:54430:38: warning: passing argument 2 of ‘k2c_LeakyReLU’ makes integer from pointer without a cast [-Wint-conversion]
54430 | k2c_LeakyReLU(&conv2d_2_output.array,&conv2d_2_output.numel,leaky_re_lu_2_alpha);
      |                                      ^~~~~~~~~~~~~~~~~~~~~~
      |                                      |
      |                                      size_t * {aka long unsigned int *}
In file included from fire_model.c:3:
./include/k2c_include.h:37:44: note: expected ‘size_t’ {aka ‘const long unsigned int’} but argument is of type ‘size_t *’ {aka ‘long unsigned int *’}
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                               ~~~~~~~~~~~~~^~~~
fire_model.c:54443:15: warning: passing argument 1 of ‘k2c_LeakyReLU’ from incompatible pointer type [-Wincompatible-pointer-types]
54443 | k2c_LeakyReLU(&dense_output.array,&dense_output.numel,leaky_re_lu_3_alpha);
      |               ^~~~~~~~~~~~~~~~~~~
      |               |
      |               float **
In file included from fire_model.c:3:
./include/k2c_include.h:37:28: note: expected ‘float *’ but argument is of type ‘float **’
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                    ~~~~~~~~^
fire_model.c:54443:35: warning: passing argument 2 of ‘k2c_LeakyReLU’ makes integer from pointer without a cast [-Wint-conversion]
54443 | k2c_LeakyReLU(&dense_output.array,&dense_output.numel,leaky_re_lu_3_alpha);
      |                                   ^~~~~~~~~~~~~~~~~~~
      |                                   |
      |                                   size_t * {aka long unsigned int *}
In file included from fire_model.c:3:
./include/k2c_include.h:37:44: note: expected ‘size_t’ {aka ‘const long unsigned int’} but argument is of type ‘size_t *’ {aka ‘long unsigned int *’}
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                               ~~~~~~~~~~~~~^~~~
fire_model.c:54459:15: warning: passing argument 1 of ‘k2c_LeakyReLU’ from incompatible pointer type [-Wincompatible-pointer-types]
54459 | k2c_LeakyReLU(&conv2d_3_output.array,&conv2d_3_output.numel,leaky_re_lu_4_alpha);
      |               ^~~~~~~~~~~~~~~~~~~~~~
      |               |
      |               float **
In file included from fire_model.c:3:
./include/k2c_include.h:37:28: note: expected ‘float *’ but argument is of type ‘float **’
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                    ~~~~~~~~^
fire_model.c:54459:38: warning: passing argument 2 of ‘k2c_LeakyReLU’ makes integer from pointer without a cast [-Wint-conversion]
54459 | k2c_LeakyReLU(&conv2d_3_output.array,&conv2d_3_output.numel,leaky_re_lu_4_alpha);
      |                                      ^~~~~~~~~~~~~~~~~~~~~~
      |                                      |
      |                                      size_t * {aka long unsigned int *}
In file included from fire_model.c:3:
./include/k2c_include.h:37:44: note: expected ‘size_t’ {aka ‘const long unsigned int’} but argument is of type ‘size_t *’ {aka ‘long unsigned int *’}
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                               ~~~~~~~~~~~~~^~~~
fire_model.c:54470:15: warning: passing argument 1 of ‘k2c_LeakyReLU’ from incompatible pointer type [-Wincompatible-pointer-types]
54470 | k2c_LeakyReLU(&conv2d_4_output.array,&conv2d_4_output.numel,leaky_re_lu_5_alpha);
      |               ^~~~~~~~~~~~~~~~~~~~~~
      |               |
      |               float **
In file included from fire_model.c:3:
./include/k2c_include.h:37:28: note: expected ‘float *’ but argument is of type ‘float **’
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                    ~~~~~~~~^
fire_model.c:54470:38: warning: passing argument 2 of ‘k2c_LeakyReLU’ makes integer from pointer without a cast [-Wint-conversion]
54470 | k2c_LeakyReLU(&conv2d_4_output.array,&conv2d_4_output.numel,leaky_re_lu_5_alpha);
      |                                      ^~~~~~~~~~~~~~~~~~~~~~
      |                                      |
      |                                      size_t * {aka long unsigned int *}
In file included from fire_model.c:3:
./include/k2c_include.h:37:44: note: expected ‘size_t’ {aka ‘const long unsigned int’} but argument is of type ‘size_t *’ {aka ‘long unsigned int *’}
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                               ~~~~~~~~~~~~~^~~~
fire_model.c:54481:15: warning: passing argument 1 of ‘k2c_LeakyReLU’ from incompatible pointer type [-Wincompatible-pointer-types]
54481 | k2c_LeakyReLU(&conv2d_5_output.array,&conv2d_5_output.numel,leaky_re_lu_6_alpha);
      |               ^~~~~~~~~~~~~~~~~~~~~~
      |               |
      |               float **
In file included from fire_model.c:3:
./include/k2c_include.h:37:28: note: expected ‘float *’ but argument is of type ‘float **’
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                    ~~~~~~~~^
fire_model.c:54481:38: warning: passing argument 2 of ‘k2c_LeakyReLU’ makes integer from pointer without a cast [-Wint-conversion]
54481 | k2c_LeakyReLU(&conv2d_5_output.array,&conv2d_5_output.numel,leaky_re_lu_6_alpha);
      |                                      ^~~~~~~~~~~~~~~~~~~~~~
      |                                      |
      |                                      size_t * {aka long unsigned int *}
In file included from fire_model.c:3:
./include/k2c_include.h:37:44: note: expected ‘size_t’ {aka ‘const long unsigned int’} but argument is of type ‘size_t *’ {aka ‘long unsigned int *’}
   37 | void k2c_LeakyReLU(float * x, const size_t size, const float alpha);
      |                               ~~~~~~~~~~~~~^~~~

(gdb) where
#0  0x0000000000403bf0 in k2c_LeakyReLU ()
#1  0x00000000004028b7 in fire_model (input_1_input=0x726cc0 <test1_input_1_input>, conv2d_6_output=0x728640 <c_conv2d_6_test1>) at fire_model.c:54402
#2  0x0000000000403183 in main () at fire_model_test_suite.c:41696

Using the master branch of keras2c.

Package dependence reproducibility.

Hey folks,

This is a nice library, but I'm running into package conflicts with Python, TF-Keras and Numpy. It seems like this library assumes an older version of Keras from tensorflow (in contrast to current stand-alone keras), but it seems difficult to trace exactly what versions of Python / Keras / TF / Numpy this is intended to work with.

What are the exact Python / Keras / Numpy versions used when this package was developed and released? I'm looking at 2020-era Python / TF / Numpy releases but still haven't been able to resolve something that actually works without throwing AttributeErrors.

Thanks!

Fail to generate c code from model using the test example

Hi there, I encountered with crashing problems when trying to generating c code from model.h5 in the example. Here is the output:
image
I use the numpy 1.26.0 and tensorflow 2.16.1 for python 3.10.12.

Any help would be greatly appreciated. This issue appears accidently that I might think It wouldn't be. Thanks.

License information is unclear

The latest commits1 changed the license information from MIT to GPL.

However, all source files, i.e., the most relevant if you e.g., vendor keras2c in your project, still state

"""
This file is part of keras2c
Copyright 2020 Rory Conlin
Licensed under MIT License
https://github.com/f0uriest/keras2c
"""

Could you please clarify whether this was intentioanl or otherwise what the actual license of the project is?
This is very crucial information when the change is from MIT to a copyleft-license like GPL.

Footnotes

  1. 4f5d488, fc62b4a, c1abf92, 708b763

Cannot generate test files.

I am using the repository as is in Master. The test generation fails and does not create the C file.
I am using VS code in windows, using an anaconda enviroment to access tensorflow. This is the output:

All checks passed
Gathering Weights
Writing layer  input_1:0
Writing layer  dense_1
Writing layer  dense_2
Writing layer  lstm_1
Writing layer  dense_3
Traceback (most recent call last):
  File "c:/Users/migel/Repositorios/test_keras2c/keras2c/mytest.py", line 9, in <module>
    k2c(model,function_name,malloc=True,num_tests=1,verbose=True)
  File "c:\Users\migel\Repositorios\test_keras2c\keras2c\keras2c\keras2c_main.py", line 218, in k2c
    malloc_vars, stateful = model2c(
  File "c:\Users\migel\Repositorios\test_keras2c\keras2c\keras2c\keras2c_main.py", line 97, in model2c
    if not subprocess.run(['astyle', '--version']).returncode:
  File "C:\Users\migel\anaconda3\envs\keras_env\lib\subprocess.py", line 489, in run
    with Popen(*popenargs, **kwargs) as process:
  File "C:\Users\migel\anaconda3\envs\keras_env\lib\subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Users\migel\anaconda3\envs\keras_env\lib\subprocess.py", line 1307, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] El sistema no puede encontrar el archivo especificado (The system cannot find the specified file)

The generated files are the following, they seem to be ok, but the test is missing.
image

I think the problem might be how I had to set-up my enviroment. The keras2c library is not installed in my anaconda enviroment. Tried adding the keras2c folder to the PYTHONPATH of my enviroment, but it is still not working
Any idea?
Thank you.

What is the reason for the significant difference between the predicted values on the python side and those predicted by keras2c?

Hallo;
Here is my problem:
This is the predicted value on the python side: [[0.00516781 0.99483216]]
This is the predicted value of keras2c: 0.0138991503 0.986100852
Keras version 2.15.0
keras2c complied by QT5.12.
​The following is my network structure:


Layer (type) Output Shape Param #

conv2d (Conv2D) (None, 43, 43, 32) 896
activation (Activation) (None, 43, 43, 32) 0
conv2d_1 (Conv2D) (None, 14, 14, 32) 9248
activation_1 (Activation) (None, 14, 14, 32) 0
max_pooling2d (MaxPooling2D) (None, 7, 7, 32) 0
dropout (Dropout) (None, 7, 7, 32) 0
conv2d_2 (Conv2D) (None, 3, 3, 64) 18496
activation_2 (Activation) (None, 3, 3, 64) 0
conv2d_3 (Conv2D) (None, 1, 1, 64) 36928
activation_3 (Activation) (None, 1, 1, 64) 0
max_pooling2d_1 (MaxPooling2D) (None, 1, 1, 64) 0
dropout_1 (Dropout) (None, 1, 1, 64) 0
flatten (Flatten) (None, 64) 0
dense (Dense) (None, 512) 33280
activation_4 (Activation) (None, 512) 0
dropout_2 (Dropout) (None, 512) 0
dense_1 (Dense) (None, 2) 1026
activation_5 (Activation) (None, 2) 0

Total params: 99874 (390.13 KB)
Trainable params: 99874 (390.13 KB)
Non-trainable params: 0 (0.00 Byte)


Regards,
LC

Runtime error

Hello,
After generating .h .c and test successfully and also compiling the test case without errors the program don't run. It crashes without output anything after calling the first test function. I also tried to generate the code with malloc (maybe my model is to big to the stack), same result. In the malloc version it is able to initialize but stops at the first call. I added a printf just before the test1 call.
image

Code: https://drive.google.com/file/d/1iTu_dCY4qEpG1v4aGMmw1bhwZ3pYx3X0/view?usp=sharing
System: Windows 10 - 64bit, gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0

Any ideas?

Thank you,

Marcelo

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.