CMSIS_5: bug in NN example code?

I’m compiling and running the NN CIFAR-10 example code on a NUCLEO_F767ZI using the terminal on MacOS. The NN execution pipeline (described in arm_nnexamples_cifar10.cpp) seems to be working until it reaches the fully connected layer. There it gets stuck. I found that the reason for this is the line: arm_q7_to_q15_reordered_no_shift(pV, vec_buffer, dim_vec), found at the top of arm_fully_connected_q7.c. When commented, the entire NN gets executed but I feel like the output is wrong: 0:0 1:23 2:23 3:0 4:11 5:11 6:11 7:11 8:23 9:11

I’m assuming that the output is in the form: image_label_id: probability, so I’d expect at least the sum of all probabilities to be 100. The given input image ( in arm_nnexamples_cifar10_inputs.h) is a cat, this category has label_id = 3

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 19 (1 by maintainers)

Most upvoted comments

@iabdalkader : If you generate image data from caffe directly, you don’t need this as caffe will take care of the mean.binaryproto subtraction. 81% matches what we got when training the network in Caffe. You should use arm_fully_connected_q7_opt function as the weight formats are different for arm_fully_connected_q7_opt and arm_fully_connected_q7.

@kwagyeman : good suggestion. We will maybe include a example python script to generate the image input data from the dataset.

Below is an example python script to download CIFAR-10 image database and automatically create the input image data to feed into the example. Hope this helps.

#!/usr/bin/env python

import numpy as np
import os

def unpickle(file):
    import pickle
    with open(file, 'rb') as fo:
        dict = pickle.load(fo)
    return dict

# Download and expand CIFAR-10 data if needed
if (os.path.isfile('cifar-10-python.tar.gz') == False):
  os.system("wget https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz")
  os.system("tar -xf cifar-10-python.tar.gz")

# First walk-through the data to create mean value
mean_array = np.zeros((32*32*3))

for batch_id in range(1,6) :
  dict = unpickle("cifar-10-batches-py/data_batch_"+str(batch_id))
  mean_array = mean_array +  0.2 * np.mean(dict['data'], axis=0) 

# convert it to uint8
mean_array = np.rint(mean_array)
mean_array = np.clip(mean_array, 0, 255)

# how many images we want to generate
num_of_images = 10

image_count = 0

#now we can output the image data from test batch
dict = unpickle("cifar-10-batches-py/test_batch")
for image_id in range(len(dict['labels'])):
  if (image_count >= num_of_images):
    break
  raw_image = dict['data'][image_id]
  label = dict['labels'][image_id]
  # subtract the image mean
  delta_image = raw_image - mean_array
  # first reshape into CHW format
  reshape_image = np.reshape(delta_image, (3, 32, 32), order='C')

  # change shape from CHW to HWC
  reshape_image = np.swapaxes(reshape_image, 0, 1)
  reshape_image = np.swapaxes(reshape_image, 1, 2)

  # saturate and make sure it is of type int8
  reshape_image = np.clip(reshape_image, -128, 127)
  input_image = reshape_image.astype('int8')

  # generate header file
  out_f = open("image_"+str(image_count)+".h", 'w')
  out_f.write("#define IMG_DATA {")
  input_image.tofile(out_f, sep=",", format="%d")
  out_f.write("}\n\n")

  out_f.write("#define TEST_LABEL "+str(label)+"\n\n");
  out_f.close()

  image_count = image_count + 1

@jafermarq , Thank you for creating the repo. I can reproduce the results that program stuck at the same exact location you were reporting. My guess is that this may be an instruction alignment issue but not 100% sure. I have tried a simple fix here that use -O3 gcc flag instead of -Os. All you need to do is to create a .json file (e.g., here) and add --profile target_O3.json to your mbed compile command.

Also, as suggested by @iabdalkader, you should use the function arm_fully_connected_q7_opt.

Let me know if this fixes the issue.

Thanks, Liangzhen