文章目录
基于pynq的数字识别神经网络加速器设计
本篇为笔者第一次进行神经网络加速器设计的工程开发流程,在此做如下整理。
python环境:python:3.6.13;tensorflow:1.14.0;numpy:1.16.0
硬件环境:vivado2019,vivado_hls2019,pynq-Z1(xc7z020clg400-1)
软件部分
1. 全连接神经网络:
本神经网络主要是进行图像识别,在人眼中图片是带有颜色的,而在电脑中图片的颜色则是使用0-1之间的灰度值表示,最为简单的黑白照片便是使用0表示白色,1表示黑色,中间值表示灰度。彩色图片则是采用红绿蓝(RGB)进行三通道混合表示。传统的数字识别思路为:对于图片中的每个像素点即矩阵中每个位置的点,对应于不同的分类结果(0-9)都一个支持率,之后将图像中对于每个分类的支持率全部加起来,支持率最高的分类就作为这张图片的识别结果,即 y = softmax(wx + b)。(其中softmax对计算结果进行归一化处理方便训练过程中的反向传播计算)
代码部分:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W) + b)
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sess = tf.InteractiveSession()
init = tf.global_variables_initializer()
sess.run(init)
for _ in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, {
x: batch_xs, y_: batch_ys})
#print(sess.run(tf.matmul(x, W) + b, {x: mnist.test.images}))
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, {
x: mnist.test.images, y_: mnist.test.labels}))
2. 卷积神经网络搭建:
通过卷积和池化不断地对图片信息进行提取,最后在全连接中实现结果的输出。同时卷积神经网络考虑到具有一定的泛化能力(不同数据集上的准确度应该都较高),会加入dropout以防止过拟合,即会在神经网络的训练过程中随机地打开或关闭一些层。
此处为数据存储代码,进过训练以后的神经网络每一层的代码需要存储下来,方便后续硬件端进行计算,这里需要注意的是为了和后面硬件端C语言的函数读取方式一致,需要根据存储数据的维度进行分类,而不是简单读入。
def Record_Tensor(tensor,name):
print ("Recording tensor "+name+" ...")
f = open('./record/'+name+'.dat', 'w')
array=tensor.eval();
#print ("The range: ["+str(np.min(array))+":"+str(np.max(array))+"]")
if(np.size(np.shape(array))==1):
Record_Array1D(array,name,f)
else:
if(np.size(np.shape(array))==2):
Record_Array2D(array,name,f)
else:
if(np.size(np.shape(array))==3):
Record_Array3D(array,name,f)
else:
Record_Array4D(array,name,f)
f.close();
def Record_Array1D(array,name,f):
for i in range(np.shape(array)[0]):
f.write(str(array[i])+"\n");
def Record_Array2D(array,name,f):
for i in range(np.shape(array)[0]):
for j in range(np.shape(array)[1]):
f.write(str(array[i][j])+"\n");
def Record_Array3D(array,name,f):
for i in range(np.shape(array)[0]):
for j in range(np.shape(array)[1]):
for k in range(np.shape(array)[2]):
f.write(str(array[i][j][k])+"\n");
def Record_Array4D(array,name,f):
for i in range(np.shape(array)[0]):
for j in range(np.shape(array)[1]):
for k in range(np.shape(array)[2]):
for l in range(np.shape(array)[3]):
f.write(str(array[i][j][k][l])+"\n");
之后便是基于tensorflow语法进行神经网络搭建。
def weight_variable(shape):
initial = tf.compat.v1.truncated_normal(shape, stddev=0.1);
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2,1], padding='SAME')
#First Convolutional Layer
with tf.name_scope('1st_CNN'