This notebook covers how to use low quantized Neural Networks on Pynq for inference on MNIST dataset by using LFC network composed of 4 fully connected layers with 1024 neurons each. There are 2 networks using different precision:
In [1]:
import bnn
This notebook performs inference on MNIST test set from http://yann.lecun.com/exdb/mnist/ which contains 10000 pictures of handwritten digits. The LFC network requires MNIST formatted input data, that's why the binary test file can be directly loaded. All other images have to be formatted to this specification (refer to url and LFC webcam examples).
At first you need to download mnist test set and labels using wget and unzip the archive as shown below: In order to be able to compare the inferred classes against the expected labels we first read the labels:
In [2]:
#get
!wget http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
!wget http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
#unzip
!gzip -d t10k-images-idx3-ubyte.gz
!gzip -d t10k-labels-idx1-ubyte.gz
#read labels
labels = []
with open("/home/xilinx/jupyter_notebooks/bnn/t10k-labels-idx1-ubyte","rb") as lbl_file:
#read magic number and number of labels (MSB first) -> MNIST header
magicNum = int.from_bytes(lbl_file.read(4), byteorder="big")
countLbl = int.from_bytes(lbl_file.read(4), byteorder="big")
#now the labels are following byte-wise
for idx in range(countLbl):
labels.append(int.from_bytes(lbl_file.read(1), byteorder="big"))
lbl_file.close()
len(labels)
Out[2]:
First of all a classifier needs to be instantiated. Using the LfcClassifier will allow to classify MNIST formatted images utilizing LFC network. There are two different runtimes available: hardware accelerated and pure software environment.
Once a classifier is instantiated the inference on MNIST images can be started using classify_mnist
or classify_mnists
methods - for both single and multiple images.
In [3]:
lfcW1A1_classifier = bnn.LfcClassifier(bnn.NETWORK_LFCW1A1,"mnist",bnn.RUNTIME_HW)
lfcW1A1_classifier.classes
Out[3]:
In [4]:
result_W1A1 = lfcW1A1_classifier.classify_mnists("/home/xilinx/jupyter_notebooks/bnn/t10k-images-idx3-ubyte")
In [5]:
lfcW1A2_classifier = bnn.LfcClassifier(bnn.NETWORK_LFCW1A2,"mnist",bnn.RUNTIME_HW)
In [6]:
result_W1A2 = lfcW1A2_classifier.classify_mnists("/home/xilinx/jupyter_notebooks/bnn/t10k-images-idx3-ubyte")
In [7]:
with open("/home/xilinx/jupyter_notebooks/bnn/10_mnist_pictures", "wb") as out_file:
with open("/home/xilinx/jupyter_notebooks/bnn/t10k-images-idx3-ubyte","rb") as img_file:
#copy magic number
out_file.write(img_file.read(4))
#set number of images
img_file.read(4)
out_file.write(bytearray.fromhex('0000000A'))
#copy row and column information
out_file.write(img_file.read(8))
#copy 10 pictures (one is 28x28, 1 pixel is 1 byte)
out_file.write(img_file.read(28*28*10))
img_file.close()
out_file.close()
Start inference
In [8]:
print("SW Inference with W1A1:")
sw_lfcW1A1_classifier = bnn.LfcClassifier(bnn.NETWORK_LFCW1A1,"mnist",bnn.RUNTIME_SW)
sw_resultW1A1 = sw_lfcW1A1_classifier.classify_mnists("/home/xilinx/jupyter_notebooks/bnn/10_mnist_pictures")
print("\nSW Inference with W1A2:")
sw_lfcW1A2_classifier = bnn.LfcClassifier(bnn.NETWORK_LFCW1A2,"mnist",bnn.RUNTIME_SW)
sw_resultW1A2 = sw_lfcW1A2_classifier.classify_mnists("/home/xilinx/jupyter_notebooks/bnn/10_mnist_pictures")
As it can be seen, pure software runtime is much slower.
In [9]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
hw_time = [lfcW1A1_classifier.usecPerImage,
lfcW1A2_classifier.usecPerImage]
sw_time = [sw_lfcW1A1_classifier.usecPerImage,
sw_lfcW1A2_classifier.usecPerImage]
x_axis = ('W1A1', 'W1A2')
y_pos = np.arange(len(x_axis))
plt.bar(y_pos-0.25, hw_time, 0.25)
plt.bar(y_pos+0.25, sw_time, 0.25)
plt.xticks(y_pos, x_axis)
plt.legend(["hardware","software"])
plt.semilogy()
plt.show()
In [10]:
#compare against labels
countRight = 0
for idx in range(len(labels)):
if labels[idx] == result_W1A1[idx]:
countRight += 1
accuracyW1A1 = countRight*100/len(labels)
countRight = 0
for idx in range(len(labels)):
if labels[idx] == result_W1A2[idx]:
countRight += 1
accuracyW1A2 = countRight*100/len(labels)
print("Accuracy W1A1: ", accuracyW1A1)
print("Accuracy W1A2: ", accuracyW1A2)
In [11]:
from pynq import Xlnk
xlnk = Xlnk()
xlnk.xlnk_reset()