• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.github/H27-Nov-2021-7566

cmake/H27-Nov-2021-673586

include/fdeep/H27-Nov-2021-8,1856,571

keras_export/H27-Nov-2021-1,9451,534

logo/H03-May-2022-

test/H03-May-2022-1,293935

.gitignoreH A D27-Nov-202184 109

FAQ.mdH A D27-Nov-202120.1 KiB544423

INSTALL.mdH A D27-Nov-20214.5 KiB136104

LICENSEH A D27-Nov-20211.1 KiB2217

README.mdH A D27-Nov-20217.9 KiB199154

README.md

1![logo](logo/fdeep.png)
2
3[![CI](https://github.com/Dobiasd/frugally-deep/workflows/ci/badge.svg)](https://github.com/Dobiasd/frugally-deep/actions)
4[![(License MIT 1.0)](https://img.shields.io/badge/license-MIT%201.0-blue.svg)][license]
5
6[license]: LICENSE
7
8frugally-deep
9=============
10
11**Use Keras models in C++ with ease**
12
13Table of contents
14-----------------
15
16* [Introduction](#introduction)
17* [Usage](#usage)
18* [Performance](#performance)
19* [Requirements and Installation](#requirements-and-installation)
20* [FAQ](#faq)
21
22Introduction
23------------
24
25Would you like to build/train a model using Keras/Python? And would you like to run the prediction (forward pass) on your model in C++ without linking your application against TensorFlow? Then frugally-deep is exactly for you.
26
27**frugally-deep**
28
29* **is a small header-only library** written in modern and pure C++.
30* is very easy to integrate and use.
31* depends only on [FunctionalPlus](https://github.com/Dobiasd/FunctionalPlus), [Eigen](http://eigen.tuxfamily.org/) and [json](https://github.com/nlohmann/json) - also header-only libraries.
32* supports inference (`model.predict`) not only for [sequential models](https://keras.io/getting-started/sequential-model-guide/) but also for computational graphs with a more complex topology, created with the [functional API](https://keras.io/getting-started/functional-api-guide/).
33* re-implements a (small) subset of TensorFlow, i.e., the operations needed to support prediction.
34* results in a much smaller binary size than linking against TensorFlow.
35* works out-of-the-box also when compiled into a 32-bit executable. (Of course, 64 bit is fine too.)
36* utterly ignores even the most powerful GPU in your system and uses only one CPU core per prediction. ;-)
37* but is quite fast on one CPU core [compared to TensorFlow](#performance), and you can run multiple predictions in parallel, thus utilizing as many CPUs as you like to improve the overall prediction throughput of your application/pipeline.
38
39
40### Supported layer types
41
42Layer types typically used in image recognition/generation are supported, making many popular model architectures possible (see [Performance section](#performance)).
43
44* `Add`, `Concatenate`, `Subtract`, `Multiply`, `Average`, `Maximum`
45* `AveragePooling1D/2D`, `GlobalAveragePooling1D/2D`
46* `Bidirectional`, `TimeDistributed`, `GRU`, `LSTM`, `CuDNNGRU`, `CuDNNLSTM`
47* `Conv1D/2D`, `SeparableConv2D`, `DepthwiseConv2D`
48* `Cropping1D/2D`, `ZeroPadding1D/2D`
49* `BatchNormalization`, `Dense`, `Flatten`, `Normalization`
50* `Dropout`, `AlphaDropout`, `GaussianDropout`, `GaussianNoise`
51* `SpatialDropout1D`, `SpatialDropout2D`, `SpatialDropout3D`
52* `RandomContrast`, `RandomFlip`, `RandomHeight`
53* `RandomRotation`, `RandomTranslation`, `RandomWidth`, `RandomZoom`
54* `MaxPooling1D/2D`, `GlobalMaxPooling1D/2D`
55* `ELU`, `LeakyReLU`, `ReLU`, `SeLU`, `PReLU`
56* `Sigmoid`, `Softmax`, `Softplus`, `Tanh`
57* `Exponential`, `GELU`, `Softsign`
58* `UpSampling1D/2D`
59* `Reshape`, `Permute`, `RepeatVector`
60* `Embedding`
61
62
63### Also supported
64
65* multiple inputs and outputs
66* nested models
67* residual connections
68* shared layers
69* variable input shapes
70* arbitrary complex model architectures / computational graphs
71* custom layers (by passing custom factory functions to `load_model`)
72
73### Currently not supported are the following:
74
75`ActivityRegularization`,
76`AveragePooling3D`,
77`Conv2DTranspose` ([why](FAQ.md#why-are-conv2dtranspose-layers-not-supported)),
78`Conv3D`,
79`ConvLSTM2D`,
80`Cropping3D`,
81`Dot`,
82`GRUCell`,
83`LocallyConnected1D`,
84`LocallyConnected2D`,
85`LSTMCell`,
86`Masking`,
87`MaxPooling3D`,
88`RepeatVector`,
89`RNN`,
90`SimpleRNN`,
91`SimpleRNNCell`,
92`StackedRNNCells`,
93`ThresholdedReLU`,
94`Upsampling3D`,
95`temporal` models
96
97Usage
98-----
99
1001) Use Keras/Python to build (`model.compile(...)`), train (`model.fit(...)`) and test (`model.evaluate(...)`) your model as usual. Then save it to a single HDF5 file using `model.save('....h5', include_optimizer=False)`. The `image_data_format` in your model must be `channels_last`, which is the default when using the TensorFlow backend. Models created with a different `image_data_format` and other backends are not supported.
101
1022) Now convert it to the frugally-deep file format with `keras_export/convert_model.py`
103
1043) Finally load it in C++ (`fdeep::load_model(...)`) and use `model.predict(...)` to invoke a forward pass with your data.
105
106The following minimal example shows the full workflow:
107
108```python
109# create_model.py
110import numpy as np
111from tensorflow.keras.layers import Input, Dense
112from tensorflow.keras.models import Model
113
114inputs = Input(shape=(4,))
115x = Dense(5, activation='relu')(inputs)
116predictions = Dense(3, activation='softmax')(x)
117model = Model(inputs=inputs, outputs=predictions)
118model.compile(loss='categorical_crossentropy', optimizer='nadam')
119
120model.fit(
121    np.asarray([[1, 2, 3, 4], [2, 3, 4, 5]]),
122    np.asarray([[1, 0, 0], [0, 0, 1]]), epochs=10)
123
124model.save('keras_model.h5', include_optimizer=False)
125```
126
127```bash
128python3 keras_export/convert_model.py keras_model.h5 fdeep_model.json
129```
130
131```cpp
132// main.cpp
133#include <fdeep/fdeep.hpp>
134int main()
135{
136    const auto model = fdeep::load_model("fdeep_model.json");
137    const auto result = model.predict(
138        {fdeep::tensor(fdeep::tensor_shape(static_cast<std::size_t>(4)),
139        std::vector<float>{1, 2, 3, 4})});
140    std::cout << fdeep::show_tensors(result) << std::endl;
141}
142```
143
144When using `convert_model.py` a test case (input and corresponding output values) is generated automatically and saved along with your model. `fdeep::load_model` runs this test to make sure the results of a forward pass in frugally-deep are the same as in Keras.
145
146For more integration examples please have a look at the [FAQ](FAQ.md).
147
148Performance
149-----------
150
151Below you can find the average durations of multiple consecutive forward passes for some popular models ran on a **single core** of an Intel Core i5-6600 CPU @ 3.30GHz. frugally-deep and TensorFlow were compiled (GCC ver. 7.1) with `g++ -O3 -march=native`. The processes were started with `CUDA_VISIBLE_DEVICES='' taskset --cpu-list 1 ...` to **disable the GPU** and to only allow usage of one CPU.
152(see used [`Dockerfile`](test/Dockerfile))
153
154| Model             | Keras + TF | frugally-deep |
155| ----------------- | ----------:| -------------:|
156| `DenseNet121`     |     0.12 s |        0.25 s |
157| `DenseNet169`     |     0.13 s |        0.28 s |
158| `DenseNet201`     |     0.16 s |        0.39 s |
159| `InceptionV3`     |     0.21 s |        0.32 s |
160| `MobileNet`       |     0.05 s |        0.15 s |
161| `MobileNetV2`     |     0.05 s |        0.17 s |
162| `NASNetLarge`     |     0.83 s |        4.03 s |
163| `NASNetMobile`    |     0.08 s |        0.32 s |
164| `ResNet101`       |     0.22 s |        0.45 s |
165| `ResNet101V2`     |     0.21 s |        0.42 s |
166| `ResNet152`       |     0.31 s |        0.65 s |
167| `ResNet152V2`     |     0.29 s |        0.61 s |
168| `ResNet50`        |     0.13 s |        0.26 s |
169| `ResNet50V2`      |     0.12 s |        0.22 s |
170| `VGG16`           |     0.40 s |        0.56 s |
171| `VGG19`           |     0.49 s |        0.68 s |
172| `Xception`        |     0.25 s |        1.20 s |
173
174Requirements and Installation
175-----------------------------
176
177- A **C++14**-compatible compiler: Compilers from these versions on are fine: GCC 4.9, Clang 3.7 (libc++ 3.7) and Visual C++ 2015
178- Python 3.7 or higher
179- TensorFlow and Keras 2.7.0 (This is the tested version, but somewhat older ones might work too.)
180
181Guides for different ways to install frugally-deep can be found in [`INSTALL.md`](INSTALL.md).
182
183FAQ
184---
185
186See [`FAQ.md`](FAQ.md)
187
188Disclaimer
189
190----------
191The API of this library still might change in the future. If you have any suggestions, find errors or want to give general feedback/criticism, I'd [love to hear from you](issues). Of course, [contributions](pulls) are also very welcome.
192
193License
194-------
195
196Distributed under the MIT License.
197(See accompanying file [`LICENSE`](LICENSE) or at
198[https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT))
199