0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

在FPGA上实现深度学习

OpenFPGA 来源:OpenFPGA 2023-02-15 09:41 次阅读

在上一篇文章中,谈到了深度学习是什么以及在 FPGA 上进行深度学习的好处。在本课程的后续文章中,我们将开始开发针对 FPGA 的深度学习设计。特别是,在本文中,我们将首先在 Python 上运行训练代码,并创建一个网络模型方便在后续 FPGA 上运行。

在后续文章中,我们将根据实际源码进行讲解。稍后将提供包括 FPGA 设计在内的所有代码。

要使用的数据集工具

MNIST 数据库

本课程针对的问题是通常称为图像分类的任务。在这个任务中,我们输出一个代表输入图像的标签。这里的标签例如是图像中物体的通用名称。

MNIST 数据库是一个包含 0 到 9 的手写数字的数据集,并为每个手写数字定义了正确的标签 (0-9)。由于输入是一张28x28的灰度图,输出最多10个类,在图像分类任务中属于非常初级的任务。除了 MNIST 之外,主要的图像分类数据集包括CIFAR10和ImageNet,并且往往会按上诉列出的顺序成为更难的问题。

MNIST 在许多深度学习教程中都有使用,因为它是一个非常简单的数据集。由于本课程的主要目的是在 FPGA 上实现深度学习,因此我们将创建一个针对 MNIST 的学习模型。

fe7783d0-a86b-11ed-bfe3-dac502259ad0.png

MNIST 数据库——维基百科

PyTorch

PyTorch是来自 Facebook 的开源深度学习框架,也是与来自 Google 的TensorFlow一起使用最频繁的框架之一。在本文中,我们将在 PyTorch 上学习和创建网络模型。

PyTorch安装参考官网步骤。我使用的 Ubuntu 16.04 LTS 上安装的 Python 3.5 不支持最新的 PyTorch,所以我使用以下命令安装了旧版本。

pipinstalltorch==1.4.0torchvision==0.5.0

由于本文的重点不在于如何使用PyTorch,所以我将省略代码的解释,尤其是学习部分。如果有兴趣,建议尝试下面的官方教程,尽管它是英文的。

卷积神经网络

卷积神经网络 (CNN) 是一种旨在在图像任务中表现出色的神经网络。本文创建的网络模型是一个卷积神经网络,该网络由以下三层和激活函数的组合组成。

全连接层

卷积层

池化层

激活函数

下面概述了每一层的处理和作用。

全连接层

全连接层是通过将输入向量乘以内部参数矩阵来输出向量的过程。如果只说神经网络没有前言比如卷积,往往指的就是这个全连接层。

fe8aa62c-a86b-11ed-bfe3-dac502259ad0.png

由于全连接层的输入是向量,所以无法得到图像中应该注意的与周围像素点的关系。在卷积神经网络中,全连接层主要用于将卷积层和池化层创建的压缩图像信息(特征)转换为标签数据(0-9)。

卷积层

卷积层是对图像进行卷积处理的层。如果熟悉图像处理,可能会称其为滤镜处理。

在卷积层中,对于输入图像中的每个像素,获取周围像素的像素值,每个像素值乘以一个数组(kernel),它是一个内参,求和就是像素值输出图像。这以图形方式表示,如下所示。

fea10322-a86b-11ed-bfe3-dac502259ad0.png

卷积神经网络的许多层都是由这个卷积层组成的,因为它以这种方式针对图像处理。

池化层

池化层是用于压缩由卷积层获得的信息的层。使用本次使用的参数,通过取图像中2x2块的最大值将图像大小减半。下图显示了最大值的减少处理。

fec523e2-a86b-11ed-bfe3-dac502259ad0.png

通过应用多个池化层,聚合图像每个部分的信息,并接近表示最终图像整体的标签信息。

激活函数

激活函数是一个非线性函数,插入在卷积层和全连接层之后。这是为了避免将实际上是线性函数的两层合并为一层。已经提出了各种类型的激活函数,但近年来 ReLU 是主要使用的激活函数。

ReLU 是 Rectified Linear Unit 的缩写。该函数会将小于0的输入值置为0,大于0的值原样输出。

创建网络模型

使用的网络模型是著名网络模型LeNet的简化版。LeNet 是早期的卷积神经网络之一,和这个一样,都是针对手写识别的。

本文使用的模型定义如下。与原来的LeNet相比,有一些不同之处,例如卷积层的核大小减小,激活函数为ReLU。

classNet(nn.Module):
def__init__(self,num_output_classes=10):
super(Net,self).__init__()


self.conv1=nn.Conv2d(in_channels=1,out_channels=4,kernel_size=3,padding=1)

#激活函数ReLU
self.relu1=nn.ReLU(inplace=True)

#
self.pool1=nn.MaxPool2d(kernel_size=2,stride=2)

#4ch->8ch,14x14->7x7
self.conv2=nn.Conv2d(in_channels=4,out_channels=8,kernel_size=3,padding=1)
self.relu2=nn.ReLU(inplace=True)
self.pool2=nn.MaxPool2d(kernel_size=2,stride=2)

#全连接层
self.fc1=nn.Linear(8*7*7,32)
self.relu3=nn.ReLU(inplace=True)

#全连接层
self.fc2=nn.Linear(32,num_output_classes)

defforward(self,x):

#激活函数ReLU
x=self.conv1(x)
x=self.relu1(x)

#缩小
x=self.pool1(x)

#2层+缩小
x=self.conv2(x)
x=self.relu2(x)
x=self.pool2(x)

#(Batch,Ch,Height,Width)->(Batch,Ch)
x=x.view(x.shape[0],-1)

#全连接层
x=self.fc1(x)
x=self.relu3(x)
x=self.fc2(x)

returnx

使用netron可视化此模型的数据流如下所示:

fed9a06a-a86b-11ed-bfe3-dac502259ad0.png

按照数据的顺序流动,首先输入一张手写图像(28×28, 1ch),在第一个Conv2d层转换为(28×28, 4ch)的图像,通过ReLU变成非负的。

然后通过 Maxpool2d 层将该图像缩小为 (14×14, 4ch) 图像。随后的 Conv2d、ReLU、MaxPool2d 遵循几乎相同的程序,生成 (7×7, 8ch) 图像。将此图像视为7x7x8 = 392度的向量,应用两次全连接层最终将输出10度的向量。此 10 阶向量中具有最大值的元素的索引 (argmax) 是推断字符 (0-9)。

学习/推理

使用上述模型训练 MNIST。这里需要执行三个步骤:

加载训练/测试数据

循环学习

测试(推理)

首先,读取数据。PyTorch 带有一个预定义的 MNIST 加载器,我们用它来加载数据(训练集/测试集)。trainloader/testloader 是定义如何读取每个数据集中数据的对象。

importtorch
importtorchvision
importtorchvision.transformsastransforms

#2.定义数据集读取方法
#获取MNIST的学习测试数据
trainset=torchvision.datasets.MNIST(root='./data',train=True,download=True,transform=transforms.ToTensor())
testset=torchvision.datasets.MNIST(root='./data',train=False,download=True,transform=transforms.ToTensor())

#数据读取方法的定义
#1步骤的每个学习测试读取16张图像
trainloader=torch.utils.data.DataLoader(trainset,batch_size=16,shuffle=True)
testloader=torch.utils.data.DataLoader(testset,batch_size=16,shuffle=False)

现在数据读取已经完成,是时候开始学习了。首先,我们定义损失函数(误差函数)和优化器。在后续的学习中,我们会朝着损失值减小的方向学习。

#损失函数,最优化器的定义
loss_func=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(net.parameters(),lr=0.0001)

学习循环像这样:从trainloader读取输入数据(inputs),纠正标签(labels),通过网络得到输出(outputs),得到带有正确标签的error(loss)。

然后我们使用一种称为误差反向传播 (loss.backward()) 的技术来计算每一层的学习方向(梯度)。优化器使用获得的梯度来优化模型(optimizer.step())。这是一步学习流程,在此代码中,重复学习直到够 10 个数据集。

由于我们将使用 FPGA 进行推理处理,因此即使不了解此处描述的学习过程也没有问题。如果你对我们为什么这样学习感兴趣,请参考上一篇文章中一些通俗易懂的文献。

#循环直到使用数据集中的所有图像10次
forepochinrange(10):
running_loss=0

#在数据集中循环
fori,datainenumerate(trainloader,0):
#导入输入批(图像,正确标签)
inputs,labels=data

#零初始化优化程序
optimizer.zero_grad()

#通过模型获取输入图像的输出标签
outputs=net(inputs)

#与正确答案的误差计算+误差反向传播
loss=loss_func(outputs,labels)
loss.backward()

#使用误差优化模型
optimizer.step()
running_loss+=loss.item()
ifi%1000==999:
print('[%d,%5d]loss:%.3f'%
(epoch+1,i+1,running_loss/1000))
running_loss=0.0

测试代码如下所示:该测试与学习循环几乎相同,但省略了学习的损失计算。scikit-learn我们还使用这里的函数来accuracy_score, confusion_matrix输出准确度和混淆矩阵。

fromsklearn.metricsimportaccuracy_score,confusion_matrix

#4.测试
ans=[]
pred=[]
fori,datainenumerate(testloader,0):
inputs,labels=data
outputs=net(inputs)

ans+=labels.tolist()
pred+=torch.argmax(outputs,1).tolist()

print('accuracy:',accuracy_score(ans,pred))
print('confusionmatrix:')
print(confusion_matrix(ans,pred))

通过到目前为止的实施,可以在 PyTorch 上训练和推断 MNIST。当我在 i7 CPU 上实际运行上述代码时,该过程在大约 3 分钟内完成。日志在下面。

[n, m] loss: X这条线表示第n个epoch(使用数据集的次数)和学习数据集中第m个数据时的损失(错误)。可以看出,随着学习的进行,损失几乎接近于 0。即使是这种非常小的网络模型也可以成功学习。

测试准确率最终显示出足够高的准确率,达到 97.26%。接下来的矩阵是混淆矩阵(confusion_matrix),其中第i行第j列的值代表正确答案i和推理结果j。这次数据的准确性足够了,结果似乎没有什么明显的偏差。这一次,我们一次性得到了足够的准确率,但是我们在原来的开发中并没有得到我们想要的准确率,所以我们在这里回顾一下模型和学习方法。

[1,1000]loss:1.765
[1,2000]loss:0.655
[1,3000]loss:0.475
...
[10,1000]loss:0.106
[10,2000]loss:0.101
[10,3000]loss:0.104
accuracy:0.9726
confusionmatrix:
[[973010020220]
[0112821002020]
[3399780127101]
[10696801205108]
[1030960012213]
[310508702074]
[1021178927020]
[1390100100617]
[51112433892710]
[56031010104970]]

最后,使用以下代码保存模型。前者是从 PyTorch 重新评估的模型文件,后者用于在 PyTorch 的 C++ API(libtorch)上读取网络模型。

#5.保存模型
#用于从PyTorch正常读取的模型文件
torch.save(net.state_dict(),'model.pt')

#保存用于从libtorch(C++API)读取的TorchScriptModule
example=torch.rand(1,1,28,28)
traced_script_module=torch.jit.trace(net,example)
traced_script_module.save('traced_model.pt')

总结

在本文中,我们使用 MNIST 数据集作为学习目标来创建、训练和推断网络模型。

使用基于 LeNet 的轻量级网络模型,我们能够在 MNIST 数据集上实现良好的准确性。在下一篇和后续文章中,我们的目标是在 FPGA 上运行该模型,并在考虑高级综合(HLS)的情况下开始 C++ 实现。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1603

    文章

    21328

    浏览量

    593267
  • 数据库
    +关注

    关注

    7

    文章

    3591

    浏览量

    63376
  • python
    +关注

    关注

    51

    文章

    4678

    浏览量

    83476
  • Ubuntu系统
    +关注

    关注

    0

    文章

    84

    浏览量

    3785
  • MNIST
    +关注

    关注

    0

    文章

    10

    浏览量

    3319

原文标题:从FPGA说起的深度学习(二)

文章出处:【微信号:Open_FPGA,微信公众号:OpenFPGA】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    相比GPU和GPP,FPGA深度学习的未来?

    设计工具日渐成熟,如今将FPGA集成到常用的深度学习框架已成为可能。未来,FPGA将有效地适应深度学习
    发表于 07-28 12:16 7370次阅读

    FPGA深度学习应用中或将取代GPU

    上涨,因为事实表明,它们的 GPU 训练和运行 深度学习模型 方面效果明显。实际,英伟达也已经对自己的业务进行了转型,之前它是一家纯粹做 GPU 和游戏的公司,现在除了作为一家云
    发表于 03-21 15:19

    Nanopi深度学习之路(1)深度学习框架分析

    就能实现!还请关注我后面的日记。实际我也是刚刚有时间学习深度学习,我是个纯初学者,但面对深度
    发表于 06-04 22:32

    【详解】FPGA深度学习的未来?

    。此外,FPGA正迅速取代ASIC和应用专用标准产品(ASSP)来实现固定功能逻辑。 FPGA市场规模预计2016年将达到100亿美元。对于深度
    发表于 08-13 09:33

    深度学习汽车中的应用

    嵌入式开发和平台抽象;TI硬件实现用于加速CNN的高度优化的内核,以及支持从开放框架(如Caffe和TensorFlow)到使用TIDL应用程序编程界面的嵌入式框架进行网络转换的转换器。有关此解决方案的更多详细信息,请阅读白
    发表于 03-13 06:45

    RK3399开发板如何去实现一种人工智能深度学习框架呢

    RK3399开发板如何去实现一种人工智能深度学习框架呢?
    发表于 03-07 07:00

    什么是深度学习?使用FPGA进行深度学习的好处?

    FPGA实现。易于适应新的神经网络结构深度学习是一个非常活跃的研究领域,每天都在设计新的 DNN。其中许多结合了现有的标准计算,但有些需要全新的计算方法。特别是
    发表于 02-17 16:56

    FPGA深度学习的未来

    FPGA深度学习的未来,学习资料,感兴趣的可以看看。
    发表于 10-26 15:29 0次下载

    深度学习方案ASIC、FPGA、GPU比较 哪种更有潜力

    几乎所有深度学习的研究者都在使用GPU,但是对比深度学习硬鉴方案,ASIC、FPGA、GPU三种究竟哪款更被看好?主要是认清对
    发表于 02-02 15:21 1w次阅读
    <b class='flag-5'>深度</b><b class='flag-5'>学习</b>方案ASIC、<b class='flag-5'>FPGA</b>、GPU比较 哪种更有潜力

    FPGA深度学习领域的应用

    本文从硬件加速的视角考察深度学习FPGA,指出有哪些趋势和创新使得这些技术相互匹配,并激发对FPGA如何帮助深度
    的头像 发表于 06-28 17:31 6573次阅读

    可编程相机305设计资料原理图:基于XC7Z020的AI 人工智能 可编程相机

    本产品为一款基于FPGA soc的支持二次开发的智能相机平台,基于大量已有的图形计算库和我们开发的支持库,用户可以使用python语言,轻松便利地进行各种视觉应用的开发,并利用fpga资源实现
    发表于 12-22 14:41 256次阅读
    可编程相机305设计资料原理图:基于XC7Z020的AI 人工智能 可编程相机

    FPGA说起的深度学习

    这是新的系列教程,在本教程中,我们将介绍使用 FPGA 实现深度学习的技术,深度学习是近年来人工
    的头像 发表于 03-03 09:52 1168次阅读

    FPGA深度学习领域有哪些优势?

    FPGA(Field-Programmable Gate Array)是一种灵活的可编程硬件设备,它在深度学习应用领域中具有许多优势。
    的头像 发表于 03-09 09:41 1444次阅读

    FPGA说起的深度学习:任务并行性

    这是新的系列教程,在本教程中,我们将介绍使用 FPGA 实现深度学习的技术,深度学习是近年来人工
    的头像 发表于 04-12 10:19 601次阅读

    FPGA说起的深度学习:数据并行性

    这是新的系列教程,在本教程中,我们将介绍使用 FPGA 实现深度学习的技术,深度学习是近年来人工
    的头像 发表于 05-04 11:22 831次阅读
    从<b class='flag-5'>FPGA</b>说起的<b class='flag-5'>深度</b><b class='flag-5'>学习</b>:数据并行性