Commit 47edc6a8 authored by eyuhar's avatar eyuhar

added gluon directory

added latest generator
parent 55f8fe07
Pipeline #122848 failed with stage
in 4 minutes and 9 seconds
......@@ -40,3 +40,12 @@ TestCAFFE2:
- ./build.sh
- RES=$(./build/src/cpp/DigitCalculator resources/images/2.jpg resources/images/3.jpg resources/images/4.png resources/images/6.png resources/images/2.jpg resources/images/3.jpg)
- "if [[ $RES != *\"SUM: 857\"* ]]; then echo \"Wrong result:\" $RES; exit 1; fi;"
TestMXNET:
stage: linux
image: registry.git.rwth-aachen.de/monticore/embeddedmontiarc/applications/mnistcalculator/mxnet:v0.0.3
script:
- cd gluon
- ./build.sh
- RES=$(./build/src/cpp/DigitCalculator resources/images/1.png resources/images/2.png resources/images/3.png resources/images/4.png resources/images/5.png resources/images/6.png)
- "if [[ $RES != *\"SUM: 579\"* ]]; then echo \"Wrong result:\" $RES; exit 1; fi;"
\ No newline at end of file
train.log
target/
model/
build/
\ No newline at end of file
cmake_minimum_required(VERSION 3.5)
project (default)
set (CMAKE_CXX_STANDARD 11)
add_subdirectory(src/cpp)
add_subdirectory(target)
# Calculator MXNET
## Prerequisites
1. Ubuntu Linux 16.04 LTS or 18.04 LTS (experimental)
2. Deep Learning Framework **MXNet**
3. Armadillo (at least armadillo version 6.600 must be used) [Official instructions at Armadillo Website](http://arma.sourceforge.net/download.html).
4. OpenCV
## Prepare the data
To create the data for training, execute:
```
bash ./prepare.sh
```
## How to Run
Generate and build the code for the EMADL model by executing:
```
bash build.sh
```
Finally, run the calculator as follows:
```
./build/src/cpp/DigitCalculator resources/images/1.png resources/images/2.png resources/images/3.png resources/images/4.png resources/images/5.png resources/images/6.png
```
You can try different images from the provided `/resources/images` directory or even create your own images for testing. Note that the application program DigitCalculator will automatically rescale the given input image to the size 32x32.
Note: Currently, the mxnet example uses CIFAR-10 data, not MNIST!
## Troubleshooting Help
ERROR: HelperA.h:79:28: error: ‘sqrtmat’ was not declared in this scope.
FIX:
Copy compiled armadillo lib and include files to usr/lib and usr/include respectively. Replace YOUR_ARMADILLO_REPOSITORY and VERSION (e.g. 8.500.1) with your corresponding information:
```
cd YOUR_ARMADILLO_REPOSITORY/armadillo-VERSION
sudo cp libarmadillo* /usr/lib
cd YOUR_ARMADILLO_REPOSITORY/armadillo-VERSION/include
sudo cp -r * /usr/include
MXNET_PATH=$(python -c "import mxnet; print(mxnet.__file__)")
MXNET_FOLDER=$(dirname $MXNET_PATH)
echo $MXNET_FOLDER
if [ ! -f $MXNET_FOLDER/libmxnet.so ]; then
echo "libmxnet.so not found at default location" $MXNET_FOLDER
echo "It should be there if the python mxnet package is installed"
echo "Either fix the installation, or adapt the ./build.sh script to locate libmxnet.so correctly"
exit 1
fi
rm -rf target
java -jar ../embedded-montiarc-emadl-generator-0.3.0-jar-with-dependencies.jar -m src/emadl/models/ -r cNNCalculator.Connector -o target -b GLUON
rm -rf build
mkdir build && cd build
echo "Building DigitClassifier.."
cmake -D MXNET_PATH=$MXNET_FOLDER/libmxnet.so ..
make
FROM registry.git.rwth-aachen.de/monticore/embeddedmontiarc/generators/emadl2cpp/integrationtests/mxnet:v0.0.3
RUN pip install opencv-python
# Install Open CV - Warning, this takes absolutely forever
RUN apt-get update && apt-get install -y libgdal-dev
RUN mkdir -p ~/opencv cd ~/opencv && \
wget https://github.com/Itseez/opencv/archive/3.0.0.zip && \
unzip 3.0.0.zip && \
rm 3.0.0.zip && \
mv opencv-3.0.0 OpenCV
RUN apt-get install -y qtbase5-dev
RUN apt-get install -y build-essential
ENV PATH="${PATH}:/usr/include/"
RUN cd OpenCV && \
mkdir build && \
cd build && \
cmake \
-DWITH_QT=ON \
-DWITH_OPENGL=ON \
-DFORCE_VTK=ON \
-DWITH_TBB=ON \
-DWITH_GDAL=ON \
-DWITH_XINE=ON \
-DBUILD_EXAMPLES=ON \
-D ENABLE_PRECOMPILED_HEADERS=OFF ..
RUN cd OpenCV/build && make -j4
RUN cd OpenCV/build && make install
RUN cd OpenCV/build && ldconfig
RUN apt-get install -y libopenblas-dev
\ No newline at end of file
from __future__ import print_function
from __future__ import division
import h5py
import numpy as np
import cv2
import os
import argparse
import errno
import random
import sys
def create_img_list(name, data_path):
dir_name = data_path + "/" + name
image_paths = []
image_class_indices = []
print(dir_name)
for class_index_name in os.listdir(dir_name):
class_dir_path = dir_name + "/" + class_index_name
if os.path.isdir(class_dir_path):
for image_name in os.listdir(class_dir_path):
image_path = class_dir_path + "/" + image_name
image_paths.append(image_path)
class_index = float(class_index_name)
image_class_indices.append(class_index)
return image_paths, image_class_indices
def create_h5_from_list(image_paths, image_class_indices, target_dir, target_file_name, input_port_name, output_port_name, shuffle=True):
img = cv2.imread(image_paths[0])
t_img = np.transpose(img, (2,0,1)).astype(np.float32)
#t_img = t_img[-1:,:,:]
#print(t_img)
channels = t_img.shape[0]
height = t_img.shape[1]
width = t_img.shape[2]
data_size = len(image_paths)
target_file = target_dir + "/" + target_file_name + ".h5"
if os.path.isfile(target_file):
print("File", target_file, "already exists. Skipping data file creation.")
return
try:
os.makedirs(target_dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
if shuffle:
combined = list(zip(image_paths, image_class_indices))
random.shuffle(combined)
image_paths[:], image_class_indices[:] = zip(*combined)
print("Creating " + target_file + " (images:" + str(data_size) + ", channels:" + str(channels) + ", height:" + str(height) + ", width:" + str(width) + "):")
with h5py.File(target_file, "w") as ofile:
in_dset = ofile.create_dataset(input_port_name, (data_size,channels, height, width), dtype=np.float32)
out_dset = ofile.create_dataset(output_port_name + "_label", (data_size,), dtype=np.float32)
for i in range(data_size):
img = cv2.imread(image_paths[i])
t_img = np.transpose(img, (2,0,1)).astype(np.float32)
#t_img = t_img[-1:,:,:]
in_dset[i] = t_img
out_dset[i] = image_class_indices[i]
#print progress
if i % 100 == 0:
percentage = 100*i / data_size
sys.stdout.write("\r{:0.1f}%".format(percentage))
sys.stdout.flush()
sys.stdout.write("\r100.0%\n")
sys.stdout.flush()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Translate image directories into hdf5 training sets for EMADL.')
parser.add_argument("--in_port", action="store", dest="in_port", default="data")
parser.add_argument("--out_port", action="store", dest="out_port", default="softmax")
parser.add_argument("--data_path", action="store", dest="data_path", default=".")
parser.add_argument("--target_path", action="store", dest="target_path", default=".")
args = parser.parse_args()
for file_name in os.listdir(args.data_path):
if file_name == "train":
image_paths, image_class_indices = create_img_list(file_name, args.data_path)
create_h5_from_list(image_paths, image_class_indices, args.target_path, file_name, args.in_port, args.out_port)
if file_name == "test":
image_paths, image_class_indices = create_img_list(file_name, args.data_path)
create_h5_from_list(image_paths, image_class_indices, args.target_path, file_name, args.in_port, args.out_port)
cmake_minimum_required(VERSION 3.5)
project(DigitCalculator CXX)
set(CMAKE_CXX_STANDARD 11)
option(MXNET_PATH "Path to libmxnet.so")
add_executable(DigitCalculator DigitCalculator.cpp)
set_target_properties(DigitCalculator PROPERTIES LINKER_LANGUAGE CXX)
find_package(OpenCV REQUIRED)
target_link_libraries(DigitCalculator ${MXNET_PATH})
set(INCLUDE_DIRS ${INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})
set(LIBS ${LIBS} ${OpenCV_LIBS})
target_link_libraries(DigitCalculator cNNCalculator_connector ${LIBS} -lblas -lopenblas)
target_include_directories(DigitCalculator PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
export(TARGETS DigitCalculator FILE DigitCalculator.cmake)
\ No newline at end of file
#include "CNNTranslator.h"
#include "cNNCalculator_connector.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <armadillo>
#include <string> //Check if it can be removed
#include <iostream>
#include <map>
int main(int argc, char* argv[]) {
if(argc < 7){ //Note: argc=1 if no arguments are provided
std::cout << "Missing argument: Path to 6 test images must be provided " << std::endl;
exit(1);
}
cNNCalculator_connector connector;
connector.init();
for(int n = 0; n < 6; n++) {
std::string filePath = argv[n+1];
if (!std::ifstream(filePath).good()) {
std::cerr << "Image loading failure, test image '" << filePath << "' does not exist." << std::endl;
exit(1);
}
cv::Mat img = cv::imread(filePath);
std::cout << "== original image size: " << img.size() << " ==" << std::endl;
// scale image to fit
cv::Size scale(28,28);
cv::resize(img, img, scale);
std::cout << "== simply resize: " << img.size() << " ==" << std::endl;
size_t channels = 1;
size_t height = img.rows;
size_t width = img.cols;
vector<float> data(channels*height*width);
for(size_t j=0; j<height; j++){
for(size_t k=0; k<width; k++){
cv::Vec3b intensity = img.at<cv::Vec3b>(j, k);
for(size_t i=0; i<channels; i++){
data[i*height*width + j*height + k] = (float) intensity[i];
}
}
}
if(n == 0)
connector.image1 = conv_to< icube >::from( CNNTranslator::translateToCube(data, vector<size_t> {channels,height,width}) );
if(n == 1)
connector.image2 = conv_to< icube >::from( CNNTranslator::translateToCube(data, vector<size_t> {channels,height,width}) );
if(n == 2)
connector.image3 = conv_to< icube >::from( CNNTranslator::translateToCube(data, vector<size_t> {channels,height,width}) );
if(n == 3)
connector.image4 = conv_to< icube >::from( CNNTranslator::translateToCube(data, vector<size_t> {channels,height,width}) );
if(n == 4)
connector.image5 = conv_to< icube >::from( CNNTranslator::translateToCube(data, vector<size_t> {channels,height,width}) );
if(n == 5)
connector.image6 = conv_to< icube >::from( CNNTranslator::translateToCube(data, vector<size_t> {channels,height,width}) );
}
connector.execute();
int classIndex = (int)connector.res;
std::cout << "== SUM: " << classIndex << std::endl;
return 0;
}
package cNNCalculator;
component Add{
ports
in Z(0:999) num1,
in Z(0:999) num2,
out Z(0:1998) sum;
implementation Math{
sum = num1 + num2;
}
}
package cNNCalculator;
component ArgMax<Z(1:oo) n = 2>{
ports in Q^{n} inputVector,
out Z(0:oo) maxIndex,
out Q maxValue;
implementation Math{
maxIndex = 0;
maxValue = inputVector(1);
for i = 2:n
if inputVector(i) > maxValue
maxIndex = i - 1;
maxValue = inputVector(i);
end
end
}
}
package cNNCalculator;
component Calculator {
ports
in Q(0:1)^10 in1_1,
in Q(0:1)^10 in1_2,
in Q(0:1)^10 in1_3,
in Q(0:1)^10 in2_1,
in Q(0:1)^10 in2_2,
in Q(0:1)^10 in2_3,
out Z(0:1998) out1;
instance ArgMax<10> number1_ones;
instance ArgMax<10> number1_tens;
instance ArgMax<10> number1_hundreds;
instance ArgMax<10> number2_ones;
instance ArgMax<10> number2_tens;
instance ArgMax<10> number2_hundreds;
instance DigitCombiner number1;
instance DigitCombiner number2;
instance Add add;
connect in1_1 -> number1_hundreds.inputVector;
connect in1_2 -> number1_tens.inputVector;
connect in1_3 -> number1_ones.inputVector;
connect in2_1 -> number2_hundreds.inputVector;
connect in2_2 -> number2_tens.inputVector;
connect in2_3 -> number2_ones.inputVector;
connect number1_ones.maxIndex -> number1.ones;
connect number1_tens.maxIndex -> number1.tens;
connect number1_hundreds.maxIndex -> number1.hundreds;
connect number2_ones.maxIndex -> number2.ones;
connect number2_tens.maxIndex -> number2.tens;
connect number2_hundreds.maxIndex -> number2.hundreds;
connect number1.number -> add.num1;
connect number2.number -> add.num2;
connect add.sum -> out1;
}
package cNNCalculator;
component Connector {
ports in Z(0:255)^{1, 28, 28} image1,
in Z(0:255)^{1, 28, 28} image2,
in Z(0:255)^{1, 28, 28} image3,
in Z(0:255)^{1, 28, 28} image4,
in Z(0:255)^{1, 28, 28} image5,
in Z(0:255)^{1, 28, 28} image6,
out Z(0:1998) res;
instance Network<10> predictor1;
instance Network<10> predictor2;
instance Network<10> predictor3;
instance Network<10> predictor4;
instance Network<10> predictor5;
instance Network<10> predictor6;
instance Calculator cal;
connect image1 -> predictor1.data;
connect image2 -> predictor2.data;
connect image3 -> predictor3.data;
connect image4 -> predictor4.data;
connect image5 -> predictor5.data;
connect image6 -> predictor6.data;
connect predictor1.softmax -> cal.in1_1;
connect predictor2.softmax -> cal.in1_2;
connect predictor3.softmax -> cal.in1_3;
connect predictor4.softmax -> cal.in2_1;
connect predictor5.softmax -> cal.in2_2;
connect predictor6.softmax -> cal.in2_3;
connect cal.out1 -> res;
}
package cNNCalculator;
component DigitCombiner{
ports
in Z(0:9) hundreds,
in Z(0:9) tens,
in Z(0:9) ones,
out Z(0:999) number;
implementation Math{
number = ones + 10 * tens + 100 * hundreds;
}
}
configuration Network{
num_epoch:1
batch_size:10
normalize:false
context:cpu
load_checkpoint:false
optimizer:sgd{
learning_rate:0.1
learning_rate_decay:0.85
step_size:1000
weight_decay:0.0
}
}
package cNNCalculator;
component Network<Z(2:oo) classes = 10>{
ports in Z(0:255)^{1, 28, 28} data,
out Q(0:1)^{classes} softmax;
implementation CNN {
def conv(channels, kernel=1, stride=1){
Convolution(kernel=(kernel,kernel),channels=channels) ->
Relu() ->
Pooling(pool_type="max", kernel=(2,2), stride=(stride,stride))
}
data ->
conv(kernel=5, channels=20, stride=2) ->
conv(kernel=5, channels=50, stride=2) ->
FullyConnected(units=500) ->
Relu() ->
Dropout() ->
FullyConnected(units=classes) ->
Softmax() ->
softmax
}
}
configuration VGG16{
num_epoch:1
batch_size:64
normalize:true
load_checkpoint:false
optimizer:adam{
learning_rate:0.01
learning_rate_decay:0.8
step_size:1000
weight_decay: 0.01
}
}
package cNNCalculator;
component VGG16{
ports in Z(0:255)^{1, 28, 28} image,
out Q(0:1)^{10} predictions;
implementation CNN {
def conv(filter, channels){
Convolution(kernel=(filter,filter), channels=channels) ->
Relu()
}
def fc(){
FullyConnected(units=100) ->
Relu() ->
Dropout(p=0.5)
}
image ->
conv(filter=2, channels=64, ->=2) ->
Pooling(pool_type="max", kernel=(2,2), stride=(1,1)) ->
fc() ->
FullyConnected(units=10) ->
Softmax() ->
predictions
}
}
cNNCalculator.Network resources/training_data
......@@ -10,11 +10,11 @@ if [ ! -f $MXNET_FOLDER/libmxnet.so ]; then
fi
rm -rf target
java -jar ../embedded-montiarc-emadl-generator-0.2.13-jar-with-dependencies.jar -m src/emadl/models/ -r cNNCalculator.Connector -o target -b MXNET
java -jar ../embedded-montiarc-emadl-generator-0.3.0-jar-with-dependencies.jar -m src/emadl/models/ -r cNNCalculator.Connector -o target -b MXNET
rm -rf build
mkdir build && cd build
echo "Building DigitClassifier.."
cmake -D MXNET_PATH=$MXNET_FOLDER/libmxnet.so ..
make
\ No newline at end of file
make
echo "Creating HDF5 dataset from image files.."
cd resources/
wget https://git.rwth-aachen.de/thomas.timmermanns/EMADL-Demo/raw/master/src/resources/data.tar.gz
tar xf data.tar.gz
rm data.tar.gz
python imgDir-to-h5.py --in_port data --out_port softmax --data_path data --target_path training_data
rm -r data
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment