老白的白

tech blogs in Zhihu

View on GitHub

神经网络的FPGA实现之坑一: MATLAB Neural Network Toolbox

最近重新“沦为”FPGA攻城狮,做一些关于神经网络的implement工作,借知乎记录一下自己踩过的坑…

工具:MATLAB 2018a,Arria 10 SoC Development Kit,Quartus II 17.0 Standard Edition

今天做第一件事情,使用MATLAB的neural network toolbox来对即将编写的硬件代码做定点运算的软件仿真,从而确定硬件实现的正确性。

坑:如何添加自定义的Layer,尤其是这个Layer里的运算不可导的情况

此处,pre-trained的数据被直接truncate成定点来计算。

基于MATLAB自身的demo Create Simple Deep Learning Network for Classification 来介绍。打开方式很简单,在Command Window输入openExample(‘nnet/TrainABasicConvolutionalNeuralNetworkForClassificationExample’)并回车。

直接运行会得到如下结果,validation的正确率为97.96%。

下面,我们将会添加一层Quantization,从而可以对比软件计算的定点结果和硬件计算的定点结果。

根据Neural Network Toolbox User’s Guide中Define a Layer with Learnable Parameters章节,我们自己编写了一个quant层,如下

classdef quantLayer < nnet.layer.Layer
    methods
        function Z = predict(layer, X)
            % Forward input data through the layer and output the result
            Z = arrayfun(@quant,X);
        end
        function [dLdX] = backward(layer, X, Z, dLdZ, memory)
            % Forward input data through the layer and output the result
            dLdX = dLdZ;
        end
    end
end

在这个类的定义中,predict给出的是forward的函数,Z是输出,X是输入,backward给出的是你希望的倒数,dLdZ是从后传递进来的倒数,此处我的predict只是将浮点数truncate成定点数,并不希望对反向传递有任何影响,故设倒数为1,从而有,dLdX = dLdZ * 1。注意,predict和backward的输入必须按照以上写法,即使函数中没有使用。

其中,quant函数(1bit sign,8bit integer,8bit fraction)为

function Z = quant(X)
    shift_8b = floor(X * 2^8);
    if shift_8b >= 0
        sat = min(shift_8b, 2^16-1);
    else
        sat = max(shift_8b, -2^16);
    end
    Z = sat/2^8;
end

这里不能使用fi函数,以及直接对矩阵或者张量进行计算,这是由于网络会生成gpuArray,以上方法无法对其进行计算,所以需要使用arrayfun来解决这个问题。其中数字可以通过参数给出,如function Z = quant(X, int, fra)。

改造一下神经网络,添加quant层,去除batch normalization层

layers = [
    imageInputLayer([28 28 1])
    
    convolution2dLayer(3,16,'Padding',1)
    quantLayer
    reluLayer
    maxPooling2dLayer(2,'Stride',2)
    
    convolution2dLayer(3,32,'Padding',1)
    quantLayer
    reluLayer
    maxPooling2dLayer(2,'Stride',2)
    
    convolution2dLayer(3,32,'Padding',1)
    quantLayer
    reluLayer
    
    fullyConnectedLayer(10)
    quantLayer
    softmaxLayer
    classificationLayer];

训练结果如下,validation正确率在99.48%

讨论:以上实验仅仅针对validation的正确率做比较,其实并不严谨。且目前并没有完整的理论证明,定点的神经网络计算要比传统的32位single格式的更加好。

MATLAB的神经网络工具包对于科研人员非常友好,可以很方便的自定义所有计算层,但是由于其训练的optimizer目前只支持SGDM,应用受到一些限制,虽然在File Exchange中有人实现了Adam,但我并没有去研究怎么使用,只是把它当作一个验证工具。

back