Skip to content

Commit

Permalink
添加自定义数据集分类部署
Browse files Browse the repository at this point in the history
  • Loading branch information
ubuntu committed Nov 11, 2021
1 parent 27f5f06 commit d106d7c
Show file tree
Hide file tree
Showing 28 changed files with 1,406 additions and 0 deletions.
93 changes: 93 additions & 0 deletions GAP8/ai_examples/classification_demo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Copyright (C) 2017 GreenWaves Technologies
# All rights reserved.

# This software may be modified and distributed under the terms
# of the BSD license. See the LICENSE file for details.

ifndef GAP_SDK_HOME
$(error Source sourceme in gap_sdk first)
endif

include common.mk

LOAD_QUANTIZATION= #-q #to load a tflite quantized model
IMAGE=$(CURDIR)/samples/12_11.pgm

io=host


RAM_FLASH_TYPE ?= HYPER
#PMSIS_OS=freertos

ifeq '$(RAM_FLASH_TYPE)' 'HYPER'
APP_CFLAGS += -DUSE_HYPER
MODEL_L3_EXEC=hram
MODEL_L3_CONST=hflash
else
APP_CFLAGS += -DUSE_SPI
CONFIG_SPIRAM = 1
MODEL_L3_EXEC=qspiram
MODEL_L3_CONST=qpsiflash
endif


QUANT_BITS?=8
BUILD_DIR=BUILD
ifeq ($(QUANT_BITS), 8)
MODEL_SQ8=1
ifeq '$(RAM_FLASH_TYPE)' 'HYPER'
NNTOOL_SCRIPT=model/nntool_script
else
NNTOOL_SCRIPT=model/nntool_script_spi
endif
MODEL_SUFFIX = _SQ8BIT
else
ifeq ($(QUANT_BITS),16)
NNTOOL_SCRIPT=model/nntool_script16
MODEL_SUFFIX = _16BIT
else
$(error Don\'t know how to build with this bit width)
endif
endif

$(info Building GAP8 mode with $(QUANT_BITS) bit quantization)

TRAINED_TFLITE_MODEL=model/$(MODEL_PREFIX).tflite

include model_decl.mk

# Here we set the memory allocation for the generated kernels
# REMEMBER THAT THE L1 MEMORY ALLOCATION MUST INCLUDE SPACE
# FOR ALLOCATED STACKS!
CLUSTER_STACK_SIZE=4028
CLUSTER_SLAVE_STACK_SIZE=1024
TOTAL_STACK_SIZE=$(shell expr $(CLUSTER_STACK_SIZE) \+ $(CLUSTER_SLAVE_STACK_SIZE) \* 7)
MODEL_L1_MEMORY=$(shell expr 60000 \- $(TOTAL_STACK_SIZE))
MODEL_L2_MEMORY=250000
MODEL_L3_MEMORY=8388608

pulpChip = GAP
PULP_APP = model

APP = model
APP_SRCS += $(MODEL_PREFIX).c $(MODEL_GEN_C) $(MODEL_COMMON_SRCS) $(CNN_LIB)

APP_CFLAGS += -g -O1 -mno-memcpy -fno-tree-loop-distribute-patterns
APP_CFLAGS += -I. -I$(MODEL_COMMON_INC) -I$(TILER_EMU_INC) -I$(TILER_INC) $(CNN_LIB_INCLUDE) -I$(MODEL_BUILD)
APP_CFLAGS += -DPERF -DAT_MODEL_PREFIX=$(MODEL_PREFIX) $(MODEL_SIZE_CFLAGS)
APP_CFLAGS += -DSTACK_SIZE=$(CLUSTER_STACK_SIZE) -DSLAVE_STACK_SIZE=$(CLUSTER_SLAVE_STACK_SIZE)
APP_CFLAGS += -DAT_IMAGE=$(IMAGE)

READFS_FILES=$(abspath $(MODEL_TENSORS))

# all depends on the model
all:: model

clean:: clean_model

include train_model.mk
include model_rules.mk
$(info APP_SRCS... $(APP_SRCS))
$(info APP_CFLAGS... $(APP_CFLAGS))
include $(RULES_DIR)/pmsis_rules.mk

67 changes: 67 additions & 0 deletions GAP8/ai_examples/classification_demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Sample MNIST Build using GAPFlow

This project includes a sample based on a simple model graph defined in Keras.

It goes from training right through to working code on GAP8 or the same code running on the PC for
debugging purposes.

* It first trains the network using keras
* It then exports the network to H5 format
* It then converts the H5 file to a TFLITE file using TensorFlow's TFLITE converter
* It then generates an nntool state file by running an nntool script with commands to adjust the tensor and activation order, fuse certain operations together and automatically quantify the graph
* It then uses this state file to generate an AutoTiler graph model
* It then compiles and runs the model to produce GAP8 code
* Finally it builds and runs the produced code on GAP8

While this example uses Makefiles the same steps could be achieved with any build system.

The process can be run to quantize the model in 16 or 8 bits weights and activations.

## Build and run without Docker
*This example uses the SDK Version `3.7`.*

To build and run on GAP8:
```
make all run
```
To build and run on GVSOC
```
make all run platform=gvsoc
```
The input image is specified in the Makefile and loaded with the functions defined in ${GAP_SDK_HOME}/libs/gap_lib/img_io/ImgIO.c

To clean the generated model and code but not the trained network type
```
make clean
```
To clean the trained keras save file type
```
make clean_train
```
To build and run the network compiled on the pc
```
make -f emul.mk all
```
This will produce an executable, model_emul, that can be used to evaluate files
```
e.g. ./model_emul images/5558_6.pgm
```
This mode allows the application to be run with PC tools like valgrind which is very interesting for debugging.
The cluster only has one core in this mode.

The build defaults to 8 bit quantization. 16 bit quantization can be selected by preceeding the build lines above with QUANT_BITS=16.
```
e.g. QUANT_BITS=16 make -f emul.mk all
```

## Build and run within the docker
*This example uses the SDK Version `3.7`.*

Navigate to top-level folder of the example
```
cd <path/to/ai-deck/repository>/GAP8/ai_examples/gapflow_model_extern/
```
Build and execute in Docker similar as the other examples
```
docker run --rm -it -v $PWD:/module/data/ --device /dev/ttyUSB0 --privileged -P gapsdk:3.7 /bin/bash -c 'export GAPY_OPENOCD_CABLE=interface/ftdi/olimex-arm-usb-tiny-h.cfg; source /gap_sdk/configs/ai_deck.sh; cd /module/data/; make clean clean_train clean_model clean_images all run'
```
16 changes: 16 additions & 0 deletions GAP8/ai_examples/classification_demo/bridge_stubs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef __BRIDGE_STUBS_H__
#define __BRIDGE_STUBS_H__

#if defined(__PULP_OS__)

#define BRIDGE_Init() {}
#define BRIDGE_Connect(__wait_bridge, __event) rt_bridge_connect(__wait_bridge, __event)
#define BRIDGE_Open(__name, __flags, __mode, __event) rt_bridge_open(__name, __flags, __mode, __event)
#define BRIDGE_Read(__file, __buffer, __size, __event) rt_bridge_read(__file, __buffer, __size, __event)
#define BRIDGE_Write(__file, __buffer, __size, __event) rt_bridge_write(__file, __buffer, __size, __event)
#define BRIDGE_Close(__file, __event) rt_bridge_close(__file, __event)
#define BRIDGE_Disconnect(__event) rt_bridge_disconnect(__event)

#endif /* __PULP_OS__ */

#endif /* __BRIDGE_STUBS_H__ */
10 changes: 10 additions & 0 deletions GAP8/ai_examples/classification_demo/common.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright (C) 2020 GreenWaves Technologies
# All rights reserved.

# This software may be modified and distributed under the terms
# of the BSD license. See the LICENSE file for details.

MODEL_PREFIX=model
AT_INPUT_WIDTH=28
AT_INPUT_HEIGHT=28
AT_INPUT_COLORS=3
9 changes: 9 additions & 0 deletions GAP8/ai_examples/classification_demo/common_rules.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (C) 2017 GreenWaves Technologies
# All rights reserved.

# This software may be modified and distributed under the terms
# of the BSD license. See the LICENSE file for details.

$(IMAGES):
(mkdir -p $(IMAGES); $(MODEL_PYTHON) model/save_samples.py -d $@ -n 5)

91 changes: 91 additions & 0 deletions GAP8/ai_examples/classification_demo/dataloader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import os
import numpy as np
from PIL import Image
import random


def savelist(data_dir):
"""
从输入根目录获取图像路径、标签列表
"""
image_paths = []
image_labels = []

print(data_dir)

image_classes = os.listdir(data_dir)
print(image_classes)

for image_class in image_classes:
sub_dir = os.path.join(data_dir + "\\" + image_class)
# 进入子类目录
image_names = os.listdir(sub_dir)
for image_name in image_names:
sub_path = os.path.join(sub_dir + "\\" + image_name)
# 操作每类图片
image_paths.append(sub_path)
image_labels.append(image_classes.index(sub_dir[38:]))


# 随机打乱
random.seed(123)
random.shuffle(image_paths)
random.seed(123)
random.shuffle(image_labels)

image_count = len(image_paths)
split = 0.2

val_image_paths = image_paths[:int(split*image_count)]
train_image_paths = image_paths[int(split*image_count):]

val_image_labels = image_labels[:int(split*image_count)]
train_image_labels = image_labels[int(split*image_count):]

return train_image_paths, train_image_labels, val_image_paths, val_image_labels




def save_as_numpy(image_paths, image_labels,str):
d = len(image_paths)
print(d)
data = np.empty((d, 28, 28, 3),dtype=np.uint8)
print(data)
while d>0:
img = Image.open(image_paths[d-1])
img = img.resize((28,28),Image.ANTIALIAS)
img_ndarray = np.array(img)
print(img_ndarray.shape)
data[d - 1] = img_ndarray
d = d - 1

print(str + "转换完成")
print(data)

d = len(image_labels)
label = np.zeros((d),dtype=np.uint8)
print(label)
while d>0:
label[d - 1] = image_labels[d-1]
d = d - 1
print(str + "转换完成")
print(label)

np.save(str + '_images.npy',data)
np.save(str + '_labels.npy',label)
np.savez(str + '.npz',image=data,label=label)




if __name__=='__main__':

data_dir = ""

train_images, train_labels, val_images, val_labels = savelist(data_dir)


save_as_numpy(train_images, train_labels, str='train')
save_as_numpy(val_images, val_labels, str='val')

74 changes: 74 additions & 0 deletions GAP8/ai_examples/classification_demo/emul.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Copyright (C) 2020 GreenWaves Technologies
# All rights reserved.

# This software may be modified and distributed under the terms
# of the BSD license. See the LICENSE file for details.

include common.mk

QUANT_BITS?=8
BUILD_DIR=BUILD
ifeq ($(QUANT_BITS), 8)
MODEL_SQ8=1
NNTOOL_SCRIPT=model/nntool_script_emul
MODEL_SUFFIX = _SQ8BIT_EMUL
else
ifeq ($(QUANT_BITS),16)
NNTOOL_SCRIPT=model/nntool_script_emul16
MODEL_SUFFIX = _16BIT_EMUL
else
$(error Don\'t know how to build with this bit width)
endif
endif
TRAINED_TFLITE_MODEL=model/$(MODEL_PREFIX).tflite

include model_decl.mk

MODEL_GEN_EXTRA_FLAGS= -f $(MODEL_BUILD)
MODEL_GENFLAGS_EXTRA+=
CC = gcc
CFLAGS += -g -m32 -O0 -D__EMUL__ -DAT_MODEL_PREFIX=$(MODEL_PREFIX) $(MODEL_SIZE_CFLAGS) -DPERF
INCLUDES = -I. -I$(TILER_EMU_INC) -I$(TILER_INC) $(CNN_LIB_INCLUDE) -I$(MODEL_BUILD) -I$(MODEL_COMMON_INC)
LFLAGS =
LIBS =
SRCS = $(MODEL_PREFIX)_emul.c $(MODEL_GEN_C) $(MODEL_COMMON_SRCS) $(CNN_LIB)
$(info CNN_LIB++ $(CNN_LIB))
$(info SRCS++ $(SRCS))
BUILD_DIR = BUILD_EMUL

OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(SRCS))

MAIN = $(MODEL_PREFIX)_emul
# Here we set the memory allocation for the generated kernels
# REMEMBER THAT THE L1 MEMORY ALLOCATION MUST INCLUDE SPACE
# FOR ALLOCATED STACKS!
CLUSTER_STACK_SIZE=2048
CLUSTER_SLAVE_STACK_SIZE=1024
TOTAL_STACK_SIZE=$(shell expr $(CLUSTER_STACK_SIZE) \+ $(CLUSTER_SLAVE_STACK_SIZE) \* 7)
MODEL_L1_MEMORY=$(shell expr 60000 \- $(TOTAL_STACK_SIZE))
MODEL_L2_MEMORY=200000
MODEL_L3_MEMORY=8388608

# hram - HyperBus RAM
# qspiram - Quad SPI RAM
MODEL_L3_EXEC=hram
# hflash - HyperBus Flash
# qpsiflash - Quad SPI Flash
MODEL_L3_CONST=hflash

all: model $(MAIN)

$(OBJS) : $(BUILD_DIR)/%.o : %.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< $(INCLUDES) -MD -MF $(basename $@).d -o $@

$(MAIN): $(OBJS)
$(CC) $(CFLAGS) -MMD -MP $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)

clean: clean_model
$(RM) -r $(BUILD_DIR)
$(RM) $(MAIN)

.PHONY: depend clean
include train_model.mk
include model_rules.mk
Loading

0 comments on commit d106d7c

Please sign in to comment.