Vitis™ AI Tutorials ResNet18, Vitis AI 3.5 README.md 번역본

KiJungKong·2024년 1월 12일
0
post-thumbnail

Vitis™ AI Tutorials

Running ResNet18 CNN Through Vitis AI 3.5 Flow for ML

  • Version: Vitis AI 3.5 with TensorFlow 2.12.0

  • Support: ZCU102, ZCU102, VCK190, VEK280, Alveo V70

  • Last update: 11 Aug 2023

Table of Contents

1 Introduction

2 Prerequisites

3 The Docker Tools Image

4 CIFAR10 Dataset

5 ImageNet Dataset

Appendix

License

1 Introduction

In this Deep Learning (DL) tutorial you will take a public domain Convolutional Neural Network (CNN) like ResNet18, already trained
on the ImageNet dataset, and run it through the Vitis AI 3.5 stack to run DL inference on FPGA devices; you will use Keras on TensorFlow 2.12.0 (shortly TF2).

이 딥러닝 튜토리얼에선 ImageNet dataset으로 학습된 ResNet18을 가져와서 Vitis AI 3.5 구성으로 FPGA devices 위에 딥러닝 추론을 돌려볼 것입니다. 그러면서 텐서플로우의 keras API를 사용할겁니다.

Assuming you have already trained your CNN and you own its original model, typically a HDF5 file with extension .h5, you will deploy such CNN on the FPGA target boards by following these steps:

CNN 모델을 이미 만들어 HDF5 확장자 포맷으로 가지고 있다고 치고 아래의 절차를 밟으면 FPGA에서 실행시킬 수 있을겁니다.

  1. (optional) Run the Model Inspector to check if the original model is compatible with the AMD Deep Processor Unit (DPU) architecture available on the target board (if not, you have to modify your CNN and retrain it).

    Model Inspector를 돌려서 원본 모델이 타겟 보드에서 사용할 AMD DPU 아키텍처랑 호환이 잘 되는지 확인해보세요.

  2. Run the Model Quantization process to generate a 8-bit fixed point (shortly "int8") model from the original 32-bit floating point CNN. If you apply the so called Post-Training Quantization (PTQ), this will be a single step, otherwise you would need to re-train - or more properly said "fine-tune" - the CNN with the Quantization-Aware-Training (QAT).

    Model Quantization을 통해서 원본 32비트 부동 소수점 CNN모델을 8비트 정수 모델로 변환하세요.

    Post-Training Quantization (PTQ)을 적용한다면 하나의 단계로 끝날 것입니다.

    Quantization-Aware-Training (QAT)을 적용한다면 미세조정을 위해 re-train을 해야 할 것입니다.

  3. (optional) Run inference with the int8 model on the Vitis AI environment (running on the host desktop) to check the prediction accuracy: if the difference is not negligible (for example it is larger than 5%, you can re-do the quantization by replacing PTQ with QAT).

    Vitis AI 환경에서 8bit 정수 모델의 추론을 돌려서 예측 정확도를 확인해보세요. 원본 모델과의 성능 차이가 5%이상 되는등 원본 모델과의 차이가 무시할 수 없을 정도라면 PTQ를 QAT로 바꾸고 quantization을 다시 해야할 것입니다.

  4. Run the Model Compilation process on the int8 model to generate the .xmodel microcode for the DPU IP soft-core of your target board.

    8bit 정수 모델의 Model Compilation을 하십쇼. 그러면 .xmodel 확장자의 마이크로코드 파일이 생성될 것이고 그 파일에는 타겟 보드의 DPU IP soft-core가 들어 있을겁니다.

  5. Compile the application running on the ARM CPU - tightly coupled with the DPU - of the target board, by using either C++ or Python code with the Vitis AI RunTime (VART) APIs.

    ARM CPU에서 구동시킬 application을 compile 하십쇼 그 application에는 Vitis AI RunTime (VART) API를 사용한 C++, 파이썬 코드가 들어가 있으며 DPU soft-core와 연동됩니다.

Based on that you will be able to measure the inference performance both in terms of average prediction accuracy and frames-per-second (fps) throughput on your target board.

이렇게 하면 타겟 보드에서의 평균 예측 정확도와 fps throughput을 측정할 수 있을 겁니다.

As a first example, in section CIFAR10 Dataset you will re-train the ResNet18 CNN with the CIFAR10 dataset, which contains small RGB images (32x32x3 size) with only 10 classes.

첫번째 예로 CIFAR10 Dataset 섹션에서는 ResNet18 CNN을 re-train할 겁니다. CIFAR10 Dataset에는 32x32x3 size의 작은 이미지들이 포함되어 있으며 10개의 클래스가 있습니다.

As a second example, in section ImageNet Dataset you will use the ResNet18 CNN as it is, in order to classify the objects from the ImageNet dataset with its own 1000 classes; you will also compare its prediction accuracy vs. its parent ResNet50 CNN taken from the Vitis AI Model Zoo.

두번째 예로 ImageNet Dataset 섹션에서는 1000개의 클래스를 가진 ImageNet dataset내의 객체들을 분류하기 위해 ResNet18 CNN을 그대로 사용해 볼겁니다. 또한 Vitis AI Model Zoo에서 가져온 원조 ResNet50 CNN과 예측 정확도를 비교해 볼 겁니다.

2 Prerequisites

Here is what you need to have and do before starting with the real content of this tutorial.

이 튜토리얼을 진행하기 위해 가지고 있어야 할 것들이랑 해야될 것들입니다.

  • Familiarity with DL principles.

    딥러닝 기초에 대한 지식이 필요합니다.

  • Accurate reading of this README.md file from the top to the bottom, before running any script.

    스크립트를 실행하기 전에 이 README.md를 처음부터 끝까지 제대로 읽으십쇼

  • Host computer with Ubuntu >= 18.04.5 (and possibly with GPU support to run the CNN training).

    Ubuntu버전은 18.04.5이상이 되야 하며 CNN training을 하기 위해 GPU support가 필요합니다.

  • Clone the entire repository of Vitis AI 3.5 stack from www.github.com/Xilinx web site.

    Vitis AI 3.5 레포지토리를 git clone하세요

  • Accurate reading of Vitis AI 3.5 User Guide 1414 (shortly UG1414).

    Vitis AI 3.5 User Guide 1414를 제대로 읽으십쇼

  • Accurate reading of Vitis AI 3.5 Online Documentation. In particular, pay attention to the installation and setup instructions for both host PC and target board, it is recommended you build a GPU-based docker image with TF2.

    Vitis AI 3.5 Online Documentation도 제대로 읽으십쇼 특히 host PC와 target board에서의 설치가이드를 좀 제대로 읽으십쇼, GPU-based docker image를 TF2와 함께 설치하는것을 추천 드립니다.

  • An AMD target board such as either:

  • The validation dataset archive with 50000 images named ILSVRC2012_img_val.tar as explained in Section 5 ImageNet Dataset.

    5 ImageNet Dataset 섹션에서 설명된대로 50000개의 이미지가 담긴 검증셋이 ILSVRC2012_img_val.tar 파일 안에 담겨 있습니다.

  • The Model Zoo archive tf2_resnet50_3.5.zip of size 190473468 bytes. as explained in Section 5.2.1 Get ResNet50 from Vitis AI Model Zoo.

    5.2.1 Get ResNet50 from Vitis AI Model Zoo 섹션에서 설명된 대로 Model Zoo가 담긴 tf2_resnet50_3.5.zip 파일은 190mb 정도 됩니다.

2.1 Working Directory

In the following of this document it is assumed you have installed Vitis AI 3.5 (shortly VAI3.5) somewhere in your file system and this will be your working directory ${WRK_DIR}, for example export WRK_DIR=/media/danieleb/DATA/VAI3.5. You have also created a folder named tutorials under such ${WRK_DIR} and you have copied this tutorial there and renamed it RESNET18. Using the command tree -d -L 2 you should see the following directories:

Vitis AI 3.5를 컴퓨터 어딘가에 설치했다고 하면 그 설치한 경로가 working directory가 됩니다. ex) export WRK_DIR=/media/danieleb/DATA/VAI3.5

그리고 ${WRK_DIR} 경로에다 tutorials이라는 이름의 폴더를 만들고 거기다가 이 튜토리얼을 복사한 후 이름을 RESNET18로 바꾸고 나서 tree -d -L 2이라는 명령어를 치면 다음과 같은 디렉토리 구성을 확인할 수 있을 겁니다.

${WRK_DIR} # your Vitis AI 3.5 working directory
.
├── bck
├── board_setup
│   ├── v70
│   └── vek280
├── demos
├── docker
│   ├── common
│   ├── conda
│   └── dockerfiles
├── docs
│   ├── docs
│   ├── _downloads
│   ├── doxygen
│   ├── _images
│   ├── _sources
│   └── _static
├── docsrc
│   ├── build
│   └── source
├── dpu
├── examples
│   ├── custom_operator
│   ├── ofa
│   ├── OnBoard
│   ├── vai_library
│   ├── vai_optimizer
│   ├── vai_profiler
│   ├── vai_quantizer
│   ├── vai_runtime
│   ├── waa
│   └── wego
├── model_zoo
│   ├── images
│   └── model-list
├── src
│   ├── AKS
│   ├── vai_library
│   ├── vai_optimizer
│   ├── vai_petalinux_recipes
│   ├── vai_quantizer
│   └── vai_runtime
├── third_party
│   ├── tflite
│   └── tvm
└── tutorials # created by you
    ├── RESNET18
    ├── TF2-Vitis-AI-Optimizer

2.2 Dos-to-Unix Conversion

In case you might get some strange errors during the execution of the scripts, you have to process -just once- all the*.sh shell and the python *.py scripts with the dos2unix utility.
In that case run the following commands from your Ubuntu host PC (out of the Vitis AI docker images):

스크립트들을 실행시키면서 이상한 에러들이 발생했을 경우에 dos2unix 유틸리티를 통해서 모든 쉘, 파이썬 스크립트들을 한번에 실행시켜야 될 겁니다.

그 경우에 Vitis AI 도커 이미지를 사용하지 말고, 다음과 같은 커맨드들을 실행시켜주세요

sudo apt-get install dos2unix
cd ${WRK_DIR}/tutorials/RESNET18 #your repo directory
for file in $(find . -name "*.sh"); do
  dos2unix ${file}
done
for file in $(find . -name "*.py"); do
  dos2unix ${file}
done
for file in $(find . -name "*.c*"); do
  dos2unix ${file}
done
for file in $(find . -name "*.h*"); do
  dos2unix ${file}
done

These operations are already included in the script clean_all.sh, launched by the run_all.sh script, which collects all the commands shown in the rest of this document.

이 작업들은 clean_all.sh에 포함되어 있으며 run_all.sh을 통해 실행됩니다. run_all.sh에는 이 글 뒤에 나오는 모든 명령어들이 들어가 있습니다.

It is strongly recommended that you familiarize with the run_all.sh script in order to understand all what it does, ultimately the entire Vitis AI flow on the host computer.

run_all.sh 스크립트가 수행하는 모든 작업, 즉 전체 Vitis AI flow를 이해하기 위해선 run_all.sh에 나오는 모든 명령어들을 제대로 이해하는것을 추천드립니다.

3 The Docker Tools Image

You have to know few things about Docker in order to run the Vitis AI smoothly on your host PC environment.

Vitis AI를 매끄럽게 돌리기 위해서는 도커에 대한 약간의 지식이 필요합니다.

3.1 Build the Image

From the Vitis AI 3.5 repository, run the following commands:

Vitis AI 3.5 레포지토지에서 다음 명령어를 입력하세요

cd ${WRK_DIR}
cd docker
./docker_build.sh -t gpu -f tf2

Once the process is finished, with the command docker images you should see something like this:

docker images에 대한 모든 작업이 끝나면 이런걸 보실 수 있을 겁니다.

REPOSITORY                      TAG                 IMAGE ID     CREATED     SIZE
xilinx/vitis-ai-tensorflow2-gpu 3.5.0.001-b56bcce50 3c5d174a1807 11-days-ago 14.4GB

3.2 Launch the Docker Image

To launch the docker container with Vitis AI tools, execute the following commands from the ${WRK_DIR} folder:

Vitis AI tool들이 담긴 docker container를 실행하기 위해서 ${WRK_DIR} 폴더에서 다음 명령어를 실행하세요

cd ${WRK_DIR} # you are now in Vitis_AI subfolder

./docker_run.sh xilinx/vitis-ai-tensorflow2-gpu:3.5.0.001-b56bcce50

conda activate vitis-ai-tensorflow2

cd /workspace/tutorials/

cd RESNET18 # your current directory

Note that the container maps the shared folder /workspace with the file system of the Host PC from where you launch the above command.
This shared folder enables you to transfer files from the Host PC to the docker container and vice versa.

컨테이너가 위의 명령어를 친 경로에 /workspace라는 공유 폴더를 마운트 시킨다는것을 잘 기억해두세요
이 공유 폴더를 통해 PC와 도커 컨테이너간에 파일을 이동시킬 겁니다.

The docker container does not have any graphic editor, so it is recommended that you work with two terminals and you point to the same folder, in one terminal you use the docker container commands and in the other terminal you open any graphic editor you like.

도커 컨테이너 안에는 GUI의 텍스트 에디터가 없으니 두개의 터미널을 열어서 같은 경로로 이동 시키고 한 터미널에서는 docker container 명령어들을 입력하시고 다른 터미널에서는 원하는 GUI의 텍스트 에디터를 여는것을 추천 드립니다.

If you need to add some further package, for example in this case I added:

특정 패키지를 추가해야될 경우에, 예를 들어 아래의 패키지를 추가 시켰다면

pip install image-classifiers

then remember to permanently save the modified docker image from a different terminal (a second one, besides the first one in which you are running the docker image),
by launching the following commands:

다음 명령어를 입력해서 도커 이미지를 실행하고 있는 터미널 말고 다른 터미널에서 수정된 도커 이미지를 영구적으로 저장해야됩니다.

docker images

sudo docker ps -l

sudo docker commit -m"latest" d9f942cdf7de   \
     xilinx/vitis-ai-tensorflow2-gpu:latest

docker images

you should see something like this:

그러면 이런걸 보실 수 있을 겁니다.

$ docker images
REPOSITORY                        TAG                  IMAGE ID       CREATED        SIZE
xilinx/vitis-ai-tensorflow2-gpu   3.5.0.001-b56bcce50  3c5d174a1807   11 days ago    14.4GB
xiinx/vitis-ai-gpu-tf2-base       latest               90d22054e565   3 weeks ago    6.43GB

$ sudo docker ps -l
[sudo] password for danieleb:
CONTAINER ID   IMAGE                                                 COMMAND                  CREATED          
d9f942cdf7de   xilinx/vitis-ai-tensorflow2-gpu:3.5.0.001-b56bcce50   "/opt/nvidia/nvidia_…"   43 minutes ago                

$ sudo docker commit -m"latest" d9f942cdf7de   xilinx/vitis-ai-tensorflow2-gpu:latest
sha256:d7af2c3ac4fb131054f9e326015d3572ceea1ec074caea0d50274ecfd76a3688

$ docker images
REPOSITORY                        TAG                                 IMAGE ID       CREATED          SIZE
xilinx/vitis-ai-tensorflow2-gpu   latest                              d7af2c3ac4fb   47 seconds ago   22.3GB
xilinx/vitis-ai-tensorflow2-gpu   3.5.0.001-b56bcce50                 3c5d174a1807   11 days ago      14.4GB
xiinx/vitis-ai-gpu-tf2-base       latest                              90d22054e565   3 weeks ago      6.43GB

3.3 Things to Know

  1. In case you "Cannot connect to the Docker daemon at unix:/var/d9f942cdf7de xilinx/vitis-ai-tensorflow2-gpu:3.5.0.001-b56bcce50 run/docker.sock. Is the docker daemon running?" just launch the following command:

    Cannot connect to the Docker daemon at unix:/var/d9f942cdf7de xilinx/vitis-ai-tensorflow2-gpu:3.5.0.001-b56bcce50 run/docker.sock. Is the docker daemon running?
    이러한 오류가 뜨면 다음 명령어를 입력하세요

    sudo systemctl restart docker
  2. Note that docker does not have an automatic garbage collection system as of now. You can use this command to do a manual garbage collection:

    현재로써는 도커에는 가비지 컬렉션 기능이 없다는 것을 주의해주세요. 다음 명령을 입력하여 수동으로 가비지 컬렉션을 할 수 있습니다.

    docker rmi -f $(docker images -f "dangling=true" -q)
  3. In order to clean the (usually huge amount of) space consumed by Docker have a look at this post: Docker Overlay2 Cleanup. The next commands are of great effect (especially the last one):

    도커가 점유하고 있는 공간을 지우기 위해서는 이 포스트(https://bobcares.com/blog/docker-overlay2-cleanup/)를 한번 참고해주세요 다음 명령어들(특히 마지막)이 효과가 매우 좋습니다.

    docker system df
    docker image prune --all
    docker system prune --all

4 CIFAR10 Dataset

In this section you will use the ResNet18 CNN on the
CIFAR10 dataset, which is composed of 10 classes of objects to be classified. It contains 60000 labeled RGB images that are 32x32 in size. This dataset was developed for the paper Learning Multiple Layers of Features from Tiny Images.

이 섹션에서 CIFAR10 dataset을 통해 ResNet18 CNN을 사용해볼겁니다. CIFAR10 dataset은 10개의 클래스로 구분되는 객체들을 분류하기 위한 데이터셋으로, 32x32 크기의 RGB 이미지 60000개로 구성되어 있습니다 이 데이터셋은 이 논문(https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf)에서 개발되었습니다.

4.1 Train ResNet18 CNN on CIFAR10

The process of training is launched via the run_all.sh script with the commands (they are all included in the subroutine main_cifar10() of the same script):

run_all.sh가 아래 명령어들을 통해서 학습 과정을 진행합니다. 이 명령어들은 run_all.sh내에 main_cifar10()이라는 서브루틴 안에 포함되어 있습니다.

cd /workspace/tutorials/RESNET18/files # your current directory
source run_all.sh run_clean_dos2unix
source run_all.sh cifar10_dataset
source run_all.sh run_cifar10_training

4.1.1 Prepare the data folders

As DL deals with image data, you have to organize your data in appropriate folders and apply some pre-processing to transform the images into data for the CNN. The subroutine cifar10_dataset() from run_all.sh file calls other python scripts to create the sub-folders train, valid, test, and calib that are located in the build/dataset/cifar10 directory and to fill them with 50000 images for training, 5000 images for validation, 5000 images for testing (taken from the 10000 images of the original test dataset) and 1000 images for the calibration process (copied from the images used during the training).

딥러닝이 이미지 데이터를 이용한다면 그 데이터들을 각각 적절한 폴더에 넣어야 하며 CNN을 위한 적절한 이미지로 변환하기 위해선 전처리 과정을 거쳐야 합니다. cifar10_dataset()이라는 서브루틴 안에는 build/dataset/cifar10라는 경로 안에 train, valid, test, calib라는 폴더를 생성한 다음 training을 위한 50000장의 이미지, 검증을 위한 5000장의 이미지, 테스트를 위한 5000장의 이미지(검증과 테스트를 위한 이미지들은 원본 테스트 dataset 10000장에서 가져왔습니다.), calibration을 위한 1000장의 이미지 (training에 사용되는 이미지에서 복사했습니다.)를 불러옵니다.

4.1.2 Preprocess the data

Typically, the CIFAR10 data are processed, using the following Python code, to normalize it from -1 to 1. Such code has to be mirrored in the C++ application that runs in the ARM® CPU of the target board.

-1과 1사이의 값으로 정규화하기 위해서 일반적으로 다음의 파이썬 코드를 통해 CIFAR10 data가 가공됩니다. 이 코드는 target board의 ARM CPU에 올라간 C++ application에도 반영되어야 합니다.

# scale data to the range of [0, 1]
x_train = x_train.astype("float32") / 255.0
x_test  = x_test.astype("float32")  / 255.0
# normalize between -1 and +1
x_train = x_train -0.5
x_train = x_train *2
x_test  = x_test  -0.5
x_test  = x_test  *2

4.1.3 Training

There are two scripts that can be chosen alternatively for training ResNet18 on the CIFAR10 dataset: train1_resnet18_cifar10.py and
train2_resnet18_cifar10.py; the first works on files of images stored into the hard disk, the second works on data loaded into the main memory of the host desktop computer. They are alternative to each other and the user can select just one.

CIFAR10 dataset을 통해 ResNet18을 학습시키기 위한 두개의 스크립트 (train1_resnet18_cifar10.py,
train2_resnet18_cifar10.py)중 하나를 선택할 수 있습니다. 첫번째는 하드디스크에 저장된 이미지 파일을 적용하는 스크립트이고 두번째는 컴퓨터의 메인 메모리의 데이터를 불러와서 적용하는 스크립트 입니다.

In both cases the CNN is taken from the Colab Classifiers, pre-trained on the ImageNet dataset; furthermore two new layers are added to the last Dense layer (with 1000 classes) of the original CNN: respectively a GlobalAveragePooling2D and another Dense layer (this one with 10 classes), as shown in the following python code fragment:

두가지 경우 모두 CNN은 Colab Classifiers을 통해 불러와지며 해당 CNN은 ImageNet dataset을 통해 pre-trained되어 있습니다. 또 그 두개의 새로운 layer들은 기존 CNN에 있는 1000개의 클래스를 가진 마지막 Dense layer에 추가됩니다.

각각 Global AveragePooling 2D와 Dense layer는 다음 파이썬 코드에 해당됩니다.

...
from classification_models.keras import Classifiers
ResNet18, preprocess_input = Classifiers.get("resnet18")
base_model = ResNet18(input_shape=(32,32,3), weights="imagenet", include_top=False)
...
x = keras.layers.GlobalAveragePooling2D()(base_model.output)
output = keras.layers.Dense(n_classes, activation="softmax")(x)
model = keras.models.Model(inputs=[base_model.input], outputs=[output])
...

Figure 1 shows the block diagram of the "new" ResNet18 trained on the CIFAR10 dataset.
The floating point models of the trained CNN are stored into the folder ./build/float.

다음 Figure 1 CIFAR10 dataset을 통해 학습된 ResNet18의 block diagram을 보여주고 있습니다. 학습된 CNN의 부동 소수점 모델은 ./build/float에 저장되어 있습니다.

:pushpin: NOTE The subclassing code shown in ResNet-18 file is not supported by the Vitis AI tools: only sequential and funcional CNN models are supported.

:pushpin:주의 ResNet-18 파일에 있는 subclassing은 Vitis AI tool들과 호환되지 않습니다. 대신 sequential, funcional CNN model들이 호환됩니다.

figure1

Figure 1: ResNet18 CNN trained on CIFAR10 dataset

4.2 Vitis AI Flow on the CNN Model

The run_all.sh script contains all the commands illustrated in the next subsections.
The entire Vitis AI flow can be launched with the command:

run_all.sh안에 다음 하위 섹션에 적힌 명령어들을 포함하고 있습니다. 모든 Vitis AI flow가 이 명령어를 통해 실행될 수 있습니다.

cd /workspace/tutorials/RESNET18/files # your current directory
source run_all.sh quantize_resnet18_cifar10
source run_all.sh compile_resnet18_cifar10
source run_all.sh prepare_archives

4.2.1 Model Inspection

The first thing to do is inspecting the floating-point CNN model.

첫번째로 해야할건 부동소수점 CNN model을 검사하는겁니다.

Vitis AI Inspector is an experimental new feature to inspect a floating-point model and show partition
results for a given DPU target architecture, together with some indications on why the layers might not be mapped to the DPU.

Vitis AI Inspector는 새로운 실험기능입니다. Vitis AI Inspector는 부동 소수점 모델을 검사하고 부분적인 결과를 보여줍니다.

그 결과에는 주어진 DPU 타겟 아키텍쳐와 지시사항 그리고 그 DPU에 해당 layer가 왜 올라갈 수 없는지에 대한 이유가 들어갑니다.

Being experimental, you can expect any possible behavior, good or bad it might be.
But if you pass it, at least you have a good chance to be able to deploy your CNN entirely on the DPU, which is certainly the optimal solution.

실험 기능이기 그게 좋든 나쁘든 어떤 변수든지 튀어나올수 있다는 것을 짐작할 수 있을 것입니다. 그래도 만약 이 단계를 거쳐간다면 최소한 CNN모델을 DPU에 올릴 수 있게 될 좋은 기회가 될 수 있을 것입니다. 그리고 그것이 최적의 솔루션일 것입니다.

Here is a fragment of python code, taken from inspect_resnet18_cifar10.py file:

아래는 inspect_resnet18_cifar10.py 파이썬 코드에서 발췌한 내용입니다.

from tensorflow_model_optimization.quantization.keras import vitis_inspect
inspector = vitis_inspect.VitisInspector(target="/opt/vitis_ai/compiler/arch/DPUCZDX8G/ZCU102/arch.json")
inspector.inspect_model(model,
                       input_shape=[1,  1000, 32, 32],
                       plot=True,
                       plot_file="float_model.svg",
                       dump_results=True,
                       dump_results_file="inspect_results.txt",
                       verbose=2)

If all the layers are supported and they can so successfully mapped to the DPU, you should see something similar to these last lines:

만약 모든 레이어들이 호환되며 성공적으로 DPU에 올라갈 수 있다면 아래 마지막 라인과 같은것을 확인할 수 있을 것입니다.

[SUMMARY INFO]:
- [Target Name]: DPUCZDX8G_ISA1_B4096
- [Total Layers]: 88
- [Layer Types]: InputLayer(1) BatchNormalization(19) ZeroPadding2D(18) Conv2D<linear>(21) Activation<relu>(18) MaxPooling2D(1) Add(8) GlobalAveragePooling2D(1) Dense<softmax>(1)
- [Partition Results]: INPUT(1) DPU(86) DPU+CPU(1)

4.2.2 Quantizing the Modified Model to int8

The quantization process is reported into vai_q_resnet18_cifar10.py python script, launched from within the quantize_resnet18_cifar10() subroutine of
run_all.sh script.

quantization 과정은 vai_q_resnet18_cifar10.py이라는 파이썬 스크립트에 의해 report됩니다. 그리고 run_all.sh내 서브루틴인 quantize_resnet18_cifar10()내에서 그것이 실행됩니다.

The generated int8 quantized model is placed in build/quantized/ folder and must have extension .h5 (which stays for HDF5 format).

생성된 8bit 정수 양자화 모델은 build/quantized/ 폴더 안에 저장될 것이며 HDF5 포맷으로 .h5라는 확장자를 가진 파일이 생성될 것입니다.

4.2.3 Compiling the Quantized Model for your Target DPU

Once the CNN has been correctly quantized in int8 format, you can compile it for the DPU architecture of your target boards,
in our case, respectively DPUCZDX8G for ZCU102 and DPUCVDX8G for VCK190, and so on for other boards.

일단 CNN이 정확히 8bit 정수 포맷으로 양자화 되면 타겟보드의 DPU 아키텍처로 그것을 컴파일 할 수 있게 됩니다.

ZCU102의 경우에는 DPUCZDX8G일 것이고 VCK190일 경우에는 DPUCVDX8G가 될 겁니다. 그리고 또 다른 보드의 경우도 여럿 있습니다.

Once the compilation process (see scripts run_all.sh and run_compile.sh) end, you should see something like this (related to ZCU102 only, for sake of conciseness):

일단 컴파일 과정이 끝나면 (run_all.sh, run_compile.sh 스크립트 파일을 참고해주세요) 아래와 같은 결과를 보실 수 있을 겁니다. (간결하게 하기 위해서 ZCU102보드의 예시만 들었습니다.)

[UNILOG][INFO] Target architecture: DPUCZDX8G_ISA1_B4096
[UNILOG][INFO] Graph name: model_1, with op num: 229
[UNILOG][INFO] Total device subgraph number 3, DPU subgraph number 1
[UNILOG][INFO] Compile done.
[UNILOG][INFO] The compiled xmodel is saved to "/workspace/tutorials/RESNET18/files/./build/compiled_zcu102/zcu102_q_train1_resnet18_cifar10_final.h5.xmodel"

The DPU code has been created into the build/target_zcu102/cifar10/train2_resnet18_cifar10.xmodel
binary file and it contains only three subgraphs,
which is the sign that everything was fine: one subgraph for the input, another for the DPU, and the last one for the output.

해당 DPU code는 build/target_zcu102/cifar10/train2_resnet18_cifar10.xmodel로 binary file로 저장되었으며 그 파일은 3개의 서브그래프를 포함합니다.

(서브그래프: DPU는 모든 CNN의 연산을 지원하지 않기 때문에, CNN을 DPU에서 실행할 수 있는 부분과 CPU에서 실행해야 하는 부분으로 나눠짐 이때, DPU에서 실행할 수 있는 부분을 subgraph라고 함)

As illustrated in Figure 2, you can visualize those three subgraphs with the graph analysis script, called by the routine analyze_graphs() from the run_all.sh script.

Figure 2에서 보여지는것처럼 이러한 서브그래프들을 graph analysis 스크립트를 통해 시각화 할 수 있므여 run_all.sh내의 analyze_graphs() 서브루틴을 통해 호출 됩니다.

figure2

Figure 2: Modified CNN model partitioned in three subgraphs by Vitis AI Compiler

Figure 2: 수정된 CNN model Vitis AI Compiler를 통해 3개의 subgraphs로 나뉘어진 모습

4.3 Run on the Target Board

You can use either VART APIs written in Python or in C++.

Python 또는 C++로 작성된 VART API를 사용할 수 있습니다.

The first option is maybe more useful for functional debugging with Visual Studio Code but gets less performance being interpreted.
The second option gets higher performance, being compiled, but it maybe less easy to be debugged.

첫번째 옵션은 vscode를 통한 기능적 디버깅에서 유용할 수 있을 것입니다. 하지만 퍼포먼스는 떨어지게 기계어로 변환될 것입니다.

두번째 옵션은 퍼포먼스가 우수하게 컴파일 되지만 디버깅이 쉽지 않을 겁니다.

The throughput measured in fps is shown only for the VEK280 board, just as a reference. For the other boards the results can be pretty different depending on the different DPU architectures and related batch size (BS).

추론의 경우 fps로 측정되는 throughput은 VEK280 보드에서만 보여지고 다른 보드에선 DPU 아키텍처와 batch size에 따라서 꽤 많이 달라질 겁니다.

All the commands illustrated in the following subsections are inside the script run_all_cifar10_target.sh, they are applied directly in the target board xxxyyy
(i.e. zcu102, vck190, v70, vek280, etc) by launching the command run_all_target.sh xxxyyy, which involves the run_all_target.sh higher level script.

다음의 하위 섹션에서 보여지는 모든 명령어들은 run_all_cifar10_target.sh안에 있습니다. 그것들은 run_all_target.sh {보드 이름} 명령어를 통해 target board에 곧바로 적용됩니다. 그리고 그 명령어들은 run_all_target.sh의 상위 레벨의 스크립트에 포함되어 있습니다.

4.3.1 Multithreading C++ Application Code

The C++ code for image classification main_int8.cc is independent of the CNN type, thanks to the abstraction done by the VART APIs; it was derived from the Vitis AI ResNet50 VART demo.

이미지 분류를 위한 main_int8.cc라는 이름의 C++ code는 VART API의 추상화 덕분에 CNN type에 독립적입니다. 또한 이 코드는 Vitis AI ResNet50 VART demo로 부터 파생되었습니다.

It is very important that the C++ code for pre-processing the images executes the same operations that you applied in the Python code of the training procedure. This is illustrated in the following C++ code fragments

이제 부터가 중요한데 이미지 전처리를 위한 C++ code가 학습을 진행하는 파이썬 코드랑 하는 역할이 똑같습니다. 아래 C++코드의 일부를 보시면 알 수 있습니다.

/*image pre-process*/
Mat image2 = cv::Mat(inHeight, inWidth, CV_8SC3);
resize(image, image2, Size(inHeight, inWidth), 0, 0, INTER_NEAREST);
for (int h = 0; h < inHeight; h++) {
  for (int w = 0; w < inWidth; w++) {
    for (int c = 0; c < 3; c++) {
      imageInputs[i * inSize + h * inWidth * 3 + w * 3 + c] = (int8_t)( (image2.at<Vec3b>(h, w)[c])/255.0f - 0.5f)*2) * input_scale ); //if you use BGR
    //imageInputs[i * inSize + h * inWidth * 3 + w * 3 +2-c] = (int8_t)( (image2.at<Vec3b>(h, w)[c])/255.0f - 0.5f)*2) * input_scale ); //if you use RGB
    }
  }
}

Note that the DPU API apply OpenCV functions to read an image file (either png or jpg or whatever format) therefore the images are seen as BGR and not as native RGB. All the training and inference steps done in this tutorial treat images as BGR, which is true also for the above C++ normalization routine.

DPU API가 OpenCV 함수들을 이미지를 읽는데 사용한다는 것을 유념해두세요 (png든 jpg든 어떤 포맷이던지) 따라서 이미지들이 원래의 RGB 순서가 아닌 BGR 순서로 되어 있습니다.

이 튜토리얼의 모든 학습과 추론 과정에서는 이미지들이 전부 BGR 순서로 되어 있습니다. 윗부분의 C++ 정규화 루틴도 마찬가지 입니다.

:pushpin: NOTE Be aware that if there was a mismatch in the preprocessing done during the training process and the preprocessing done during the inference process then you would get incorrect predictions. In this context "mismatch" means different operations (for example different ways of normalizing data).

학습과정에서 완료된 전처리와 추론과정에서 완료된 전처리에서 서로 불일치가 존재할 경우 부정확한 예측 결과가 나올 수 있음을 주의해주세요 이 문맥에서의 불일치의 의미는 다른 처리 방식을 의미합니다. (예를 들어 데이터 정규화를 다른 방식으로 하든지)

4.3.2 Run-Time Execution

It is possible and straight-forward to compile the application directly on the target (besides compiling it into the host computer environment).
In fact this is what the script run_all_cifar10_target.sh does, when launched on the target.

타겟에서 직접 application을 컴파일 하는것이 가능하며 이 방식이 더 간단하면서 쉽습니다. (PC 환경에서 컴파일 하는거 말고)

Turn on your target board and establish a serial communication with a putty terminal from Ubuntu or with a TeraTerm terminal from your Windows host PC.

타겟 보드를 켜고 우분투라면 putty를 통해 윈도우라면 TeraTerm을 통해 직렬통신으로 연결하세요

Ensure that you have an Ethernet point-to-point cable connection with the correct IP addresses to enable ssh communication in order to quickly transfer files to the target board with scp from Ubuntu or pscp.exe from Windows host PC. For example, you can set the IP addresses of the target board to be 192.168.1.217 while the host PC is 192.168.1.140.

정확한 IP 주소로 이더넷 연결이 잘 되었는지 확인해주세요 그래야 ssh연결을 할 수 있습니다. ssh로 연결 하시면 빠르게 타겟 보드로 우분투의 scp 또는 윈도우의 pscp.exe를 이용해서 파일을 옮길 수 있습니다. 예를들면 타겟보드의 IP 주소를 192.168.1.217, 192.168.1.140로 설정하실 수 있습니다.

Once a tar file of the build/target_zcu102 (or build/target_vck190, etc) folder has been created, copy it from the host PC to the target board. For example, in case of an Ubuntu PC, use the following command:

일단 build/target_{칩 이름}의 tar 파일이 생성되면 그걸 pc에서 타겟보드로 복사하십쇼 우분투의 경우 다음의 명령어를 치시면 됩니다.

scp target_zcu102.tar root@192.168.1.217:~/

From the target board terminal, run the following commands (in case of VEK280):

타겟 보드의 터미널에선 다음의 명령어를 치시면 됩니다. (VEK280의 경우)

tar -xvf target_vek280.tar
cd target_vek280
bash -x ./cifar10/run_all_cifar10_target.sh vek280

With this command, the cifar10_test.tar archive with the 5000 test images will be uncompressed.

이 명령어를 통해 5000개의 테스트 이미지들을 압축한 cifar10_test.tar이 압축 해제될겁니다.

The application based on VART C++ APIs is built with the build_app.sh script and finally launched for each CNN, the effective top-5 classification accuracy is checked by a python script check_runtime_top5_cifar10.py which is launched from within
the cifar10_performance.sh script.

VART C++ API로 만든 application은 build_app.sh script에 의해 빌드 되고 실행됩니다. 그리고 각 CNN에서 check_runtime_top5_cifar10.py라는 파이썬 스크립트 파일을 이용하여 top-5 classification accuracy를 체크합니다. 그리고 그 파이썬 스크립트는 cifar10_performance.sh안에서 실행됩니다.

4.3.3 Performance

On the VEK2800 board, the purely DPU performance (not counting the CPU tasks) measured in fps is:

VEK2800 board에서 DPU performance는 cpu task의 갯수를 측정하는 방식이 아닌 아래와 같이 fps값을 계산해서 측정됩니다.

  • ~11011 fps with 1 thread,

  • ~17828 fps with 3 threads.

The top-1 and top-5 average prediction accuracy measured at run time are:

런타임 동안 측정된 top-1 and top-5 average prediction accuracy는 아래와 같습니다.

./rpt/predictions_cifar10_resnet18.log  has  35008  lines
number of total images predicted  4999
number of top1 false predictions  761
number of top1 right predictions  4238
number of top5 false predictions  42
number of top5 right predictions  4957
top-1 accuracy = 0.85
top-5 accuracy = 0.99

5 ImageNet Dataset

The ImageNet dataset is very sophisticated in comparison with CIFAR10 and it requires proper python scripts to run inference. To get practice with CNNs using the ImageNet dataset you will start with ResNet50, then you will adapt its python code to the ResNet18 case.

ImageNet dataset은 CIFAR10보다는 더 잘 되어 있습니다. 그리고 추론을 돌리기 위해선 적절한 파이썬 스크립트가 필요합니다. ImageNet dataset을 통한 CNN을 실습하기 위해 먼저 ResNet50 부터 시작할것입니다. 그리고 나서 그 파이썬 코드에 ResNet18의 경우를 적용해볼겁니다.

For your information, an academic torrent can be used to download the whole ImageNet since direct downloads are not supported any longer (note that you need a couple hundred GB of free disk space in order to do this); a few examples of such torrents are:

전체 ImageNet은 토렌트로 다운로드가 가능합니다. 직접 다운로드하는것은 더이상 지원하지 않습니다. 몇백 GB 정도의 공간이 디스크에 남아 있어야 한다는 점을 염두해두세요) 아래는 예시 토렌트 링크입니다.

The run_all.sh script contains all the commands illustrated in the next subsections, with command source run_all main_imagenet (using the subroutine main_imagenet() from the same script).

run_all.sh 스크립트는 다음 하위 섹션에 있는 모든 명령어들을 포함합니다. run_all.sh안에 main_imagenet()안의 서브루틴으로써 source run_all main_imagenet 라는 명령어가 있습니다.

Before running that script you have to generate the val_dataset.zip archive with 500 images (the last ones of the original 50000 dataset) resized to have one of their dimensions equal to 256, as explained in the following subsection 5.1.

스크립트를 실행하기 전에 500개의 이미지를 압축한 val_dataset.zip파일을 생성해야 합니다. 그리고 그 500개의 이미지는 원본 50000개의 dataset의 마지막 이미지들 입니다. 그 500개의 이미지들은 256의 크기를 갖도록 리사이징 됩니다. 이러한 내용은 하위섹션 5.1에 설명되어 있습니다.

5.1 Prepare the Test Images

5.1.1 Download the ImageNet Validation Dataset

Since you do not need to re-train your CNN and you just want to make predictions (inference) with, you can download only the ImageNet validation dataset, named ILSVRC2012_img_val.tar, from either ImageNet 2012 or Download ImageNet Data web sites.

CNN 모델을 re-train할 필요가 없고 단순히 추론을 돌리고 싶을 뿐이기 때문에 ImageNet 검증셋만 다운로드 하시면 됩니다. 그 검증셋은 ILSVRC2012_img_val.tar라는 이름의 파일입니다. 아래 두개의 사이트에서 다운 받으실 수 있습니다.

http://academictorrents.com/collection/imagenet-2012

http://www.image-net.org/download.php

The file imagenet1000_clsidx_to_labels.txt contains the objects that compose the 1000 classes of ImageNet dataset: the index class is the left column (from 0 to 999) and the class name is the right column string:

imagenet1000_clsidx_to_labels.txt 파일은 ImageNet dataset의 1000개의 클래스들로 구성된 객체를 포함합니다. index class는 왼쪽열이며 0에서 999로 넘버링 되어 있습니다. 그리고 그 class name은 그 오른쪽 열에 있습니다.

Class indexClass name
0'tench, Tinca tinca'
1'goldfish, Carassius auratus'
2'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias'
. . .. . .

5.1.2 The "short val.txt" File

You need the short val.txt file to map the validation images into the corresponding classes with a number. Again, for your comfort it is placed already in this repository just for the 500 images used in the test. Note that the original val.txt file lists 50000 images with their file name and class index.

검증 이미지들을 해당하는 클래스에 숫자로 매칭하기 위해 short val.txt가 필요합니다. 쉽게 할 수 있도록 테스트에 이용되는 500개의 이미지를 위한 그 파일이 이미 레포지토리 넣어 두었습니다. original val.txt 안에는 원본 50000장의 이미지에 각각 해당하는 file name 그리고 class index들이 리스트 되어 있다는것을 기억해 두세요

Furthermore, for the ImageNet dataset, the name of the object related to the class of short val.txt can be found in another file named words.txt;
in fact those two files can be considered a simplification of the information that can be found in the imagenet_class_index.json - available in the modelzoo/tf2_resnet50_3.5 folder - which is related to the training dataset.

더 나아가 ImageNet dataset을 위해 short val.txt의 클래스와 관련된 객체의 이름은 words.txt라는 이름의 파일 안에서 찾을 수 있습니다. 사실 그 두개의 파일은 imagenet_class_index.json에서 찾은 정보를 단순화 한것 뿐 입니다. 그 json파일은 modelzoo/tf2_resnet50_3.5 folder안에 있습니다. 그리고 그것은 training dataset과 관련되어있습니다.

For example the goldfish class which appears in line 2 of words.txt is coded as 1 in the second record "1": ["n01443537", "goldfish"] of imagenet_class_index.json and it appears at line 85 of short val.txt file, regarding the image ILSVRC2012_val_00049585.JPEG.

예를 들어 goldfish 클래스는 words.txt의 두번째 라인에서 찾을 수 있고 1로 넘버링 되어 있습니다. 그리고 또한 imagenet_class_index.json파일의 두번째 record에 "1": ["n01443537", "goldfish"]로 적혀져 있습니다. 그리고 또한 short val.txt 파일의 85번째 라인에서도 찾을 수 있습니다. 그리고 그것은 ILSVRC2012_val_00049585.JPEG라는 이름의 이미지 파일과 관련되 있습니다.

The code in imagenet_config.py therefore creates a list class_list where such class goldfish has class index 1 stored in the index_list which is indeed the second line of words.txt file:

따라서 imagenet_config.py 코드는 class_list라는 이름의 리스트를 만듭니다. 거기에는 goldfish와 같은 클래스가 class index 1로 되어 있으며 index_list에 저장되어 있습니다. index_list는 words.txt파일의 두번째 라인에 진짜로 존재합니다.

Class nameClass index
tench0
goldfish1
great white shark2
tiger shark3
hammerhead4
. . .. . .
bolete997
ear997
toilet tissue999

Note that imagenet_config.py also creates a dictionary labelNames_dict where such the goldfish image image ILSVRC2012_val_00049585.JPEG has indeed a class index of 1 :

imagenet_config.py는 또한 labelNames_dict라는 dictionary를 만든다는것을 주목해주세요 그 dictionary안에는 이러한 goldfish 이미지(ILSVRC2012_val_00049585.JPEG)가 1이라는 class index를 가지고 있습니다.

Class nameClass index
. . .. . .
ILSVRC2012_val_000495851
. . .. . .

This way to encode the ImageNet classes is applied consistently in this tutorial by all the python scripts that evaluate the top-1 and top-5 average prediction accuracy of the CNN.

ImageNet 클래스를 encode 하기 위한 이 방법은 이 튜토리얼에서 계속 쓰일 것입니다. CNN의 top-1, top-5 average prediction accuracy를 계산하는 파이썬 스크립트에 의해서 말이죠

If you wish to download the ImageNet original val.txt file for all the 50000 images of the validation dataset, you have to execute the following commands (be careful not to overwrite the short val.txt file of this repository):

ImageNet의 50000개의 검증셋 이미지와 관련된 original val.txt를 다운받고 싶다면 다음 명령어를 실행하세요 (이 레포지토리 안에 있는 short val.txt를 덮어쓰지 않도록 주의해주세요)

mkdir tmp
cd tmp
wget -c http://dl.caffe.berkeleyvision.org/caffe_ilsvrc12.tar.gz
tar -xvf caffe_ilsvrc12.tar.gz
mv val.txt ..
cd ..
rm -r tmp

The file words.txt was generated with the following fragment of python code applied to the imagenet_class_index.json file:

words.txt는 다음의 파이썬 코드의 한 부분에 의해서 생성됩니다.

그리고 그 코드는 imagenet_class_index.json 파일에 적용됩니다.

def gen_dict(name2class_file):
    fr = open(name2class_file, 'r')
    class2name_dict = json.load(fr)
    print(class2name_dict)
    for k in range(1000):
        print(class2name_dict[str(k)][1])
    print(class2name_dict.values())
    print(class2name_dict.keys())
    name2class_dict = {}
    for key in class2name_dict.keys():
        name2class_dict[class2name_dict[key][0]] = key

    return name2class_dict

Alternatively, you can find the words.txt file in the ResNet50 VART example or in the imagenet1000_clsidx_to_labels.txt file.

그 대신에 words.txt파일을 ResNet50 VART example 안에서 찾으실수도 있고

imagenet1000_clsidx_to_labels.txt 안에서 찾으실수도 있습니다.

5.1.3 Generate the Test Images Archive

Having both original files, the (~6.7GB) ILSVRC2012_img_val.tar archive and the short val.txt with the list of the last 500 images (from the 50000) and their class number, you can now create a smaller archive, val_dataset.zip.

ILSVRC2012_img_val.tar (~6.7GB) 압축파일과 50000장의 이미지에서 뽑은 마지막 부분의 500개의 이미지의 리스트와 그 이미지 각각의 클래스 넘버가 담긴 short val.txt를 갖고 있다면 드디어 val_dataset.zip라는 더 작은 압축파일을 생성할 수 있습니다.

Here are the commands that you have to launch from within the docker image (they are already part of the prepare_imagenet_test_images() subroutine from the run_all.sh script), see the self explaining comments:

도커 이미지 안에서 실행시켜야할 명령어들입니다.

그 명령어들은 run_all.sh의 하위 루틴인 prepare_imagenet_test_images()의 한 부분입니다.

각 코드에 달려있는 주석을 잘 보십쇼

# enter in the docker image
#cd ${WRK_DIR} # you are now in Vitis_AI subfolder
#./docker_run.sh xilinx/vitis-ai-tensorflow2-gpu:3.5.0.001-b56bcce50
#conda activate vitis-ai-tensorflow2
#cd /workspace/tutorials/

# starting directory
cd /workspace/tutorials/RESNET18/files/
cd modelzoo/ImageNet/ # your current directory
# the ILSVRC2012_img_val.tar is supposed to be already here, after your download

# make a temporary directory one level below
mkdir val_dataset
mv ILSVRC2012_img_val.tar ./val_dataset/
# expand the archive
cd val_dataset
tar -xvf ILSVRC2012_img_val.tar > /dev/null
# move back the archive one level above
mv ILSVRC2012_img_val.tar ../
cd ..
# check all the 50000 images are in val_dataset folder
ls -l ./val_dataset | wc

You should see the following text:

다음의 텍스트를 보셔야 합니다.

$ ls -l ./val_dataset | wc
  50001  450002 4050014

Now run the imagenet_val_dataset.py script:

imagenet_val_dataset.py 스크립트를 실행하십쇼

python3 imagenet_val_dataset.py

You should see the following text:

그러면 다음의 텍스트를 보셔야 합니다.

val_dataset.zip archive is ready with  500 images

Now copy that archive to the target/imagenet folder:

그리고 그 압축 파일을 target/imagenet으로 옮기십쇼

cp -i val_dataset.zip ../../target/imagenet

You are ready to work with both ResNet50 and ResNet18 CNNs.
If you are not interested into experimenting ResNet50, you can skip Section 5.2 ResNet50 and jump directly to the next Section 5.3 ResNet18.

드디어 ResNet50과 ResNet18 CNNs를 작업 하실 수 있게 됩니다.

만약 ResNet50를 테스트 하는데에 관심이 없다면 5.2 ResNet50 섹션을 건너 뛰시고 바로 5.3 ResNet18 섹션으로 넘어가십시오

5.2 ResNet50

5.2.1 Get ResNet50 from Vitis AI Model Zoo

You have to download the tf2_resnet50_3.5.zip archive of ResNet50 model reported in model.yaml file.

model.yaml에 기록된 ResNet50 model를 압축한 tf2_resnet50_3.5.zip 압축파일을 다운로드 하셔야 합니다.

As the file name says, such CNN has been trained with ImageNet dataset with RGB images of input size 224x224 and it requires a computation of 7.76 GOPs per image.

파일의 이름과 같이 이러한 CNN은 224x224의 입력 사이즈를 가진 RGB image로 이루어진 ImageNet dataset을 통해 이미 학습되어 있습니다. 그리고 이미지당 7.76 GOPs (Giga Operations Per Second)의 연산 성능을 필요로 합니다.

Put the tf2_resnet50_3.5.zip archive in the modelzoo folder and unzip it there to generate the new folder modelzoo/tf2_resnet50_3.5.

tf2_resnet50_3.5.zip 압축파일을 modelzoo 폴더 안에 넣으시고 그 폴더 안에 압축을 풀으십쇼 그러면 새로운 폴더(modelzoo/tf2_resnet50_3.5)가 생성될겁니다.

Note that the original ResNet50 trained on the ImageNet dataset has the following parameters:

원본 ResNet50은 ImageNet dataset을 이용하여 학습되어 다음의 매개변수를 가진다는 것을 인지하고 계십쇼

Total params:         25,636,712
Trainable params:     25,583,592
Non-trainable params:     53,120

5.2.2 Evaluate Original and Quantized Models

The python script eval_resnet50.py does the following actions:

eval_resnet50.py 파이썬 스크립트는 다음의 작업을 합니다.

  1. it loads the original 32-bit floating point model from tensorflow.keras.applications, note that such model is exactly the same which is already available inside the Vitis AI Model Zoo;

    tensorflow.keras.applications을 통해서 원본 32bit 부동소수점 모델을 불러옵니다. 이러한 모델은 정확히 Vitis AI Model Zoo에서 이용 가능한 것들과 일치한다는 것을 기억해 두십쇼

  2. with such model, it evaluates the top1 and top5 average prediction accuracy on the 500 images available in the val_dataset.zip archive;

    이러한 모델을 통해서 val_dataset.zip 압축파일에 있는 500개의 이미지들에 대한 top1, top5 average prediction accuracy를 측정합니다.

  3. it quantizes the CNN into int8 fixed point and saves it in .h5 format; again such quantized model is exactly the same which is available inside the Vitis AI Model Zoo;

    기존 CNN을 8비트 정수 모델로 퀀타이제이션해서 .h5 format으로 저장합니다. 이러한 quantized model은 Vitis AI Model Zoo에 있는것과 일치합니다.

  4. with such quantized model it evaluates the top1 and top5 average prediction accuracy on the same 500 images.

    이러한 quantized model을 통해 같은 500개의 이미지에 대한 top1, top5 average prediction accuracy를 측정합니다.

You have to execute the following commands directly from the Vitis AI docker tools image:

Vitis AI docker tools image에 다음의 명령어를 실행하십쇼

cd /workspace/tutorials/RESNET18/files
cd modelzoo/ImageNet
unzip val_dataset.zip
cd ../..
bash ./run_all.sh quantize_resnet50_imagenet

Note that the prediction accuracy is quite sensible to the image preprocessing, which is a cascade of aspect ratio preserving resize followed by image cropping (see file eval_resnet50.py), as shown in the following fragment:

그 prediction accuracy는 꽤 이미지 전처리 과정에 민감하다는것을 염두해 두세요 그 이미지 전처리 과정은 image cropping에 따라 가로 세로 비율을 유지하는 리사이징을 합니다. (eval_resnet50.py 파일을 보십쇼) 다음 부분에 나와 있습니다.

img2 = cv2.imread(filename)
#B, G, R = cv2.split(img2)     #resnet18
#img = cv2.merge([R, G, B])    #resnet18
img = img2                     #resnet50
height, width = img.shape[0], img.shape[1]
img = img.astype(float)

# aspect_preserving_resize
smaller_dim = np.min([height, width])
_RESIZE_MIN = 256
scale_ratio = _RESIZE_MIN*1.0 / (smaller_dim*1.0)
new_height = int(height * scale_ratio)
new_width = int(width * scale_ratio)
resized_img = cv2.resize(img, (new_width, new_height), interpolation = cv2.INTER_LINEAR )
#resized_img = img

# central_crop
crop_height = 224
crop_width = 224
amount_to_be_cropped_h = (new_height - crop_height)
crop_top = amount_to_be_cropped_h // 2
amount_to_be_cropped_w = (new_width - crop_width)
crop_left = amount_to_be_cropped_w // 2
cropped_img = resized_img[crop_top:crop_top+crop_height, crop_left:crop_left+crop_width, :]

# sub mean
#_R_MEAN =     0 #resnet18
#_G_MEAN =     0 #resnet18
#_B_MEAN =     0 #resnet18
_R_MEAN = 123.68 #resnet50
_G_MEAN = 116.78 #resnet50
_B_MEAN = 103.94 #resnet50
_CHANNEL_MEANS = [_B_MEAN, _G_MEAN, _R_MEAN]
means = np.expand_dims(np.expand_dims(_CHANNEL_MEANS, 0), 0)
meaned_img = cropped_img - means

A possible, brutal, alternative is just rescaling the image without any cropping and aspect ratio preserving and related cropping, as shown in the following fragment of code:

이미지를 어떤 크롭과정과 크롭에 따라 가로 세로 비율을 유지하는 과정이 없이 rescaling만 하는 이 방식은 가능은 하지만 덜 정확한 대안입니다. 다음 코드에 나와 있습니다.

img2 = cv2.imread(filename)
#B, G, R = cv2.split(img2)     #resnet18
#img = cv2.merge([R, G, B])    #resnet18
img = img2                     #resnet50

# rescale without preseving teh aspect ratio and with no crop
cropped_img = cv2.resize(img, (224, 224), interpolation = cv2.INTER_CUBIC)

# sub mean
#_R_MEAN =     0 #resnet18
#_G_MEAN =     0 #resnet18
#_B_MEAN =     0 #resnet18
_R_MEAN = 123.68 #resnet50
_G_MEAN = 116.78 #resnet50
_B_MEAN = 103.94 #resnet50
_CHANNEL_MEANS = [_B_MEAN, _G_MEAN, _R_MEAN]
means = np.expand_dims(np.expand_dims(_CHANNEL_MEANS, 0), 0)
meaned_img = cropped_img - means

From one hand, with the "original" preprocessing code you should see something like this:

한편으로는 원래의 전처리 코드에선 이러한 코드를 보실 수 있을 겁니다.

  • original 32-bit floating point model

    Original  ResNet50 top1, top5:  0.750, 0.924
  • quantized int8 model:

    Quantized ResNet50 top1, top5:  0.744, 0.920

On the other hand, with the "brutal" preprocessing code you should see something like this:

또 한편으로는 이러한 덜 정확하고 덜 정교한 전처리 코드를 보실 수 있을 겁니다.

  • original 32-bit floating point model

    Original  ResNet50 top1, top5:  0.698, 0.908
  • quantized int8 model:

    Quantized ResNet50 top1, top5:  0.689, 0.905

This is indeed quite a big difference, which highlights -once again- the importance of the right preprocessing.

이것은 정말 큰 차이를 불러옵니다. 이것은 올바른 전처리의 중요성을 한번 더 강조합니다.

5.3 ResNet18

Similarly to what done in the previous section 5.2.2, the python script eval_resnet18.py does the following actions:

섹션 5.2.2에서 했던 것과 동일합니다. eval_resnet18.py 파이썬 스크립트는 다음의 것들을 수행합니다.

  1. it loads the original 32-bit floating point model from the Colab Classifiers;

    Colab Classifiers으로 부터 원본 32bit 부동소수점 모델을 불러옵니다.

  2. with such model, it evaluates the top1 and top5 average prediction accuracy on the 500 images available in the val_dataset.zip archive;

    이러한 모델을 통해서 val_dataset.zip 압축파일에 있는 500개의 이미지들에 대한 top1, top5 average prediction accuracy를 측정합니다.

  3. it quantizes the CNN into int8 fixed point and saves it in .h5 format;

    기존 CNN을 8비트 정수 모델로 퀀타이제이션해서 .h5 format으로 저장합니다.

  4. with such quantized model it evaluates the top1 and top5 average prediction accuracy on the same 500 images.

    이러한 quantized model을 통해 같은 500개의 이미지에 대한 top1, top5 average prediction accuracy를 측정합니다.

Note that the original ResNet18 trained on the ImageNet dataset has the following parameters:

ImageNet dataset을 통해 학습한 원본 ResNet18은 다음과 같은 파라미터들을 갖는다는것을 기억해두세요

Total params:         11,699,889
Trainable params:     11,691,947
Non-trainable params:      7,942

You have to execute the following commands directly from the Vitis AI docker tools image:

Vitis AI docker tools image에 다음에 명령어들을 실행 시키십쇼

cd /workspace/tutorials/RESNET18/files
cd modelzoo/ImageNet
unzip val_dataset.zip
cd ../..
bash ./run_all.sh quantize_resnet18_imagenet

Similarly to what already done in the case of ResNet50 CNN, if you check the prediction accuracy of ResNet18 CNN with the original preprocessing code you should see something like this:

ResNet50 CNN에서 했던거랑 같이 original preprocessing code을 통해 ResNet18 CNN의 prediction accuracy을 확인해야한다면 이러한 것들을 보셔야 합니다.

  • original 32-bit floating point model

    Original  ResNet18 top1, top5:  0.694, 0.902
  • quantized int8 model

    Quantized ResNet18 top1, top5:  0.651, 0.873

On the other hand, with the "brutal" preprocessing code you should see something like this:

한편으로는 덜 정교한 전처리 코드를 썼다면 이러한 것들을 보실 수 있을 겁니다.

  • original 32-bit floating point model

    Original  ResNet18 top1, top5:  0.656, 0.882
  • quantized int8 model

    Quantized ResNet18 top1, top5:  0.606, 0.859

Again, as in the case of ResNet50 CNN, you can see quite a big difference in the prediction accuracy, depending on the preprocessing method applied.

ResNet50 CNN의 경우에선 적용한 전처리방식에 따라서 예측 정확도에서 꽤 많은 차이점들을 보실 수 있을 겁니다.

Furthermore, note that the pre-processing applied during the ResNet18 training is quite different from the one applied to train ResNet50:

더 나아가 ResNet18 학습중에 적용된 전처리는 ResNet50에 적용된것과 꽤 다르다는것을 인지해 두세요

  1. the mean values are supposed to be 0,0,0 (ResNet18) instead of 123.68, 116.78, 103.94 (ResNet50);

    평균값은 ResNet50에선 123.68, 116.78, 103.94인 것과는 달리 ResNet18에서는 0,0,0이어야 됩니다.

  2. images are managed as RGB (ResNet18) and not as BGR (ResNet50).

    ResNet50에선 이미지가 BGR순서대로 이뤄지는것이 아니라 RGB순으로 이뤄집니다.

You can easily verify this by looking at the code differences in the two files eval_resnet18.py and
eval_resnet50.py.

eval_resnet18.py와 eval_resnet50.py의 코드를 비교해보면서 쉽게 이를 확인할 수 있습니다.

5.4 Run on the Target Board

The throughput measured in fps is shown only for the VEK280 board, just as a reference. For the other boards the results can be pretty different depending on the different DPU architectures and related batch size (BS).

fps로 측정된 throughput은 VEK280 board에서만 보여집니다. 참고하자면 다른 보드에선 DPU architectures와 그것의 batch size에 따라 꽤 다릅니다.

All the commands illustrated in the following subsections are inside the script run_all_imagenet_target.sh, they are applied directly in the target board xxxyyy
(i.e. zcu102, vck190, v70, vek280, etc) by launching the command run_all_target.sh xxxyyy, which involves the run_all_target.sh higher level script.

다음 하위 섹션에 있는 모든 명령어들은 run_all_imagenet_target.sh 스크립트 안에 있습니다. 그리고 run_all_target.sh {보드 이름} 명령어를 통해 타겟보드에 직접 적용됩니다. 그리고 run_all_target.sh의 상위 스크립트안에 이것들이 포함되어 있습니다.

5.4.1 Multithreading C++ Application Code

The C++ code for image classification main_resnet50.cc can launch both ResNet18 and ResNet50 CNNs. The only difference is in the preprocessing and in the mean values, so the variable is_resnet50 is used to check if ResNet50 (is_resnet50==1) or if ResNet18 (is_resnet50==0). Here is the C++ code fragment for pre-processing the images:

이미지 분류를 위한 main_resnet50.cc 은 ResNet18과 ResNet50 CNNs 둘다 실행 시킬 수 있습니다. 차이점은 전처리 과정과 평균값입니다. 따라서 is_resnet50 변수가 1일때는 ResNet50을 실행하고 0일때는 ResNet18을 실행합니다. 다음은 이미지 전처리를 위한 C++ code의 한 부분 입니다.

  float mean[3];
  if (is_resnet50==1)
  {
    // B G R format for ResNet50 CNN
    mean[0] = 104; mean[1] = 116.78; mean[2] = 123.68;
  }
  else //it is ResNet18 CNN
  {
    mean[0] = 0; mean[1] = 0; mean[2] = 0;
  }

  /*image pre-process*/
  Mat image2 = cv::Mat(inHeight, inWidth, CV_32FC3);
  resize(image, image2, Size(inHeight, inWidth),  interpolation=INTER_CUBIC);
  for (int h = 0; h < inHeight; h++)
  {
    for (int w = 0; w < inWidth; w++)
    {
      for (int c = 0; c < 3; c++)
      {
        int addr;
        if (is_resnet50==1) // resnet50 works in BGR format
          addr = c;
        else // resnet18 works in RGB format
          addr = 2-c;
        imageInputs[i*inSize + h*inWidth*3 + w*3 + addr] = (int8_t)((image2.at<Vec3b>(h, w)[c] - mean[c]) * input_scale);
        }
    }
  }

Note that the DPU API apply OpenCV functions to read an image file (either png or jpg or whatever format) therefore the images are seen as BGR and not as native RGB. All the training and inference steps done in this tutorial treat images as BGR, which is true also for the above C++ normalization routine.

png든 jpg이든 어떤 format으로 되있던지 DPU API가 이미지를 읽기 위해 OpenCV함수를 사용한다는점을 기억해 두십쇼 따라서 이미지는 RGB순서가 아니라 BGR순으로 되어 있습니다. 모든 학습과 추론 단계는 BGR로 이미지를 다루면서 진행됩니다. C++ 정규화 루틴에서조차 마찬가지 입니다.

5.4.2 Run-Time Execution

It is possible and straight-forward to compile the application directly on the target (besides compiling it into the host computer environment).
In fact this is what the script run_all_imagenet_target.sh does, when launched on the target.

Turn on your target board and establish a serial communication with a putty terminal from Ubuntu or with a TeraTerm terminal from your Windows host PC.

Ensure that you have an Ethernet point-to-point cable connection with the correct IP addresses to enable ssh communication in order to quickly transfer files to the target board with scp from Ubuntu or pscp.exe from Windows host PC. For example, you can set the IP addresses of the target board to be 192.168.1.217 while the host PC is 192.168.1.140.

Once a tar file of the build/target_zcu102 (or build/target_vck190) folder has been created, copy it from the host PC to the target board. For example, in case of an Ubuntu PC, use the following command:

scp target_zcu102.tar root@192.168.1.217:~/

From the target board terminal, run the following commands (in case of ZCU102):

tar -xvf target_zcu102.tar
cd target_zcu102
bash -x ./imagenet/run_all_imagenet_target.sh zcu102

With this command, the val_dataset.zip archive with the 500 test images will be uncompressed.

The application based on VART C++ APIs is built with the build_resnet50.sh script and finally launched for each CNN, the effective top-5 classification accuracy is checked by a python script check_runtime_top1_imagenet.py which is launched from within
the imagenet_performance.sh script.

5.4.3 ResNet50 Performance

On the VEK280 board, the purely DPU performance (not counting the CPU tasks) measured in fps is:

  • ~2997 fps with 1 thread,

  • ~4685 fps with 3 threads.

The top-1 average prediction accuracy measured at run time is:

./rpt/predictions_resnet50_imagenet.log  has  3510  lines
number of total images predicted  499
number of top1 false predictions  153
number of top1 right predictions  346
top1 accuracy = 0.690

The preprocessing applied in the C++ code top-1 accuracy is the "brutal" one, just applying the images resize without preserving the aspect ratio, as done in the training phase of the CNN algorithmic development.

The value of 0.690 is pretty closed to the 0.698 result we have got when evaluating the quantized model in the host Vitis AI environment; remember that by applying a better preprocessing in the C++ code you should achieve a result closed to 0.750.

Alternatively to changing the C++ code, you could prepare - once forever- test images that are already preprocessed in the same way which was applied during the CNN training.

5.4.4 ResNet18 Performance

On the VEK280 board, the purely DPU performance (not counting the CPU tasks) measured in fps is:

  • ~3964 fps with 1 thread,

  • ~7169 fps with 3 threads.

Indeed ResNet18 achieves higher fps being "smaller" than ResNet50, which is expected.

The top-1 average prediction accuracy measured at run time is:

./rpt/predictions_resnet18_imagenet.log  has  3510  lines
number of total images predicted  499
number of top1 false predictions  212
number of top1 right predictions  287
top1 accuracy = 0.580

Also this 0.580 top-1 result is achieved with the "brutal" preprocessing in the C++ application and it should be compared with the 0.606 obtained while evaluating the quantized model in the host environment (with a better preprocessing you should achieve a value closed to 0.651).

Similarly to the ResNet50 case, alternatively to changing the C++ code, you could prepare - once forever- test images already preprocessed in the same way that was applied during the CNN training.

Appendix

UART connectivity (PuTTY, minicom, etc)

For more details, see 5 Linux/Unix Commands For Connecting To The Serial Console.

Figure A1.1 illustrate some screeshot taken while using the minicom utility,
the following code illustrate how installing it or other alternative tools:

#sudo apt install setserial # alternative tool to minicom
#sudo apt install cu        # alternative tool to minicom
#sudo apt install putty     # alternative tool to minicom
sudo apt-get install minicom
sudo minicom -s

figureA31

figureA31

figureA31

figureA31

Figure A1.1: Working with minicom tool

License

The MIT License (MIT)

Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

XD106 | © Copyright 2022 Xilinx, Inc.

profile
공기정

0개의 댓글

관련 채용 정보