你觉得这篇文章怎么样? 帮助我们为您提供更好的内容。
Thank you! Your feedback has been received.
There was a problem submitting your feedback, please try again later.
你觉得这篇文章怎么样?
作者 |
嘉钧 |
难度 |
普通 |
材料表 |
|
本篇文章将使用Jetson Nano做出一个非常简单的猫狗分类器,其中用到PyTorch的ImageFolder做数据集并且用DataLoader将数据集加载的技术,并且学会用自己建置的CNN来训练,最后取出测试图片来做预测 ( 如上图 )。
Jetson Nano远程、确认环境
今天我们要在Jetson nano这块开发版上运作,而我们公司已经有许多Jetson nano的相关介绍、应用,所以就不多作介绍了,连结放在这里给大家参考https://blog.cavedu.com/tag/jetson-nano/,远程联机的部份我们使用Wireless Network Watcher查看Nano的IP地址,在选项 > 进阶选项 > 使用下列网络卡 > 选择以太网络,点击确定进行扫描就可以找到Jetson nano的虚拟IP
接着可使用MobaXterm或Jupyter Notebook进行内网的远程,两者都有文件系统可以直接进行文件传输,相当好用!在MobaXterm的部份,直接上网安装点击Session输入IP地址、用户账号、密码即可使用;而Jupyter Notebook的部份,Jetson Nano已经有帮我们设定好Notebook的远程功能,所以只要在PC端开启浏览器输入http://{你的JetsonNano的IP地址}:8888/,输入密码即可登入;本次范例将使用Jupyter Notebook来运作。
以下为使用MobaXterm操作的接口:
以下为使用Jupyter Notebook操作的接口,建议先新增一个文件夹当作工作区,新增后可以开始一个Terminal跟Jupyter Notebook;Termial用来安装套件、Jupyter用来撰写与执行程序:
Kaggle
介绍
今天使用的数据集会从Kaggle上面下载下来,这是一个数据建模和数据分析竞赛平台,每年都会办机器学习、深度学习的比赛,也有励志成为机器学习工程师的人会反复地在上面刷各种数据集取得好成绩。
数据下载的链接https://www.kaggle.com/c/dogs-vs-cats/overview/description
关于Kaggle数据集下载的方法有两种:第一种是直接下载,第二种则是透过Kaggle提供的API进行下载,今天也教大家如何使用API下载。
使用API下载Kaggle数据集
第一步、安装Kaggle API
可在Jupyter Notebook中执行:
!pip3 install -U -q kaggle
也可以在Terminal中执行
pip3 install -U -q kaggle
两者差别只在于Jupyter中要使用命令需要加上惊叹号来与程序代码作区别!
第二步、取得认证JSON檔
右上方大头贴 > My Account > 下拉至API字段并点击 Create New API Token就可以取得认证的JSON檔
注意存放位置!
这边下载后会提醒你要放到使用装置的 ~/.kaggle 位置,等等新增到Jetson Nano中要特别注意!
第三步、将认证档新增到Jetson Nano
输入以下程序代码,将 {usr}、{API key} 修改成自己的名称、密钥即可,执行之后Jetson Nano中就有kaggle中你的认证档了,接下来直接进行下载。
第四步、下载dataset到特定文件夹
这段的程序代码是从Kaggle数据集的网页中Data的信息中可以找到,其中 -p的自变量是下载到指定目录:
第五步、确认数据并解压缩
数据处理
提供的数据是train跟test1两个文件夹,在train这个文件夹中总共有25000笔资料,我们将前九张照片显示出来看看
可以注意到数据的名称是 {label}.{id}.jpg,我们的目标是要将猫跟狗两种不同的数据分到不同的文件夹当中,所以们我会先新建一个属于猫跟狗的文件夹,在透过档名来做分类。
先导入函式库以及宣告基本的目录地址:
确认目录是否存在,如果没有就创建一个:
接下来就是主要整理的程序代码了:
整理完可以发现猫跟狗都已经到各自的文件夹了,各有12500张照片:
透过torch制作数据集
在PyTorch当中客制化数据集是必要的,因为有时候你的数据是「一张照片配一个标签」有时候是「一张照片配多个标签」甚至还有个多元的标签形式,所以这边会提到怎么去制作自己的数据集。
Dataset、DataLoader之间的关系
PyTorch将所有数据打包在torch.utils.data.Dataset 当中,这边可以选择你要怎么提取你的数据集 ( 单笔 ),像是前面所说的一张照片配一个卷标或者搭配更复杂卷标,也可以在建置数据集的时候使用数据增强,透过变形、裁切来增加数据量、神经网络模型的强健度;宣告完之后再将 Dataset 打包进 torch.utils.data.DataLoader 当中去推送,这边你可以选择一次要丢几张照片出来进行平行运算。目前我比较常用的有两种定义数据集的方式,如果是已经用文件夹分类好的就可以使用ImageFolder 来制作数据集,如果要取得更多讯息就会客制化一个数据集。
使用ImageFolder建置数据集
这是torch提供最一般的数据集整理方式,我们先前已经将猫跟狗都丢进各自的文件夹了,所以等等直接使用这种简单粗暴的建制方式。
程序代码如下,在建置数据集的同时我们会先定义transform,这个目的通常用于数据处理、增强,可以做裁切、变形、转文件等功能,也是很重要的环节:
我们将数据集拿出来看可以发现猫跟狗已经帮我们分类成0跟1了:
再来会注意到一个问题,我将前五张图片拿出来查看大小,发现每一张图片的大小都不一样,这时候必须去处理维度的问题,不然卷积神经网络没办法跑
通常遇到这种问题最简单粗暴的方式是直接在transform的地方加上resize,当然会有更好的解法但这边暂时先不讲述,我们将所有的图片都先缩放到 224 * 224并且转换成Tensor后做一下正规化。
使用DataLoader批次丢出数据
这边我为了防止跑太久将循环限制在10次,可以注意到每一次都出去都是16张 ( 维度为 [16, 3, 224, 224] ),并且从label那边可以看出来都是打乱的。
建立一个卷积神经网络
卷积神经网络的概念就不赘述,主要流程就是 卷积( Conv ) > 池化 ( MaxPool ) > 摊平 ( view ) > 全连接 ( linear ) > 输出 (维度要注意),这边我在最后一层加了softmax让两者加起来为1比较好看,除此之外要注意的地方是必须要自己去计算每经过一层卷积池化,图片会变成多大,因为最后摊平的时候必须要先宣告数据输入的维度是多少,计算公式为:
所以的会发现全连阶层的第一层输入是 128 * 28 * 28,其中128就是最后一层conv的kernel数量,28*28则是自己算出来的。
可以将神经网络打印出来或者导入一笔Data看看
最后输出是二维的因为有猫跟狗两个类别,如果位置0的数值比较大代表神经网络判断为猫,反之位置1的数值比较大则是判断为狗:
开始训练
先将基本的设定好,这边要注意的是我将模型丢到GPU中去训练,因为是分类问题所以使用CrossEntropy当作损失函数,最后使用Adam来当优化器。
训练之前记得先将张量也丢到GPU中,其余的训练流程皆与之前教学雷同,我特别将每次迭代的Loss存下用来可视化用,这边我看到网络上很多人会使用model.train()、model.eval(),这是torch自动会将 BatchNorm、Dropout在验证的时候关掉,由于我们现在自己建的神经网络没有这两层所以其实是可以不用写的,不过碍于之后会陆续增加技术,BatchNorm是一定会写入的,所以现在大家可以先习惯写这两行,训练开始前将模型设成训练模式,结束的时候设成验证模式。
训练完的结果,在一般计算机使用RTX 1080训练耗费了约545秒,而JetsonNano上使用gpu训练每一次epoch约1300~1350秒,5个回合训练完大概是6500秒左右也就是几乎快两个小时了,看似效能差距很大,但是其实考虑到它的价位、体积以及运算能力,其实是相当的不错了!
我有先将loss储存起来,所以这边可以直接调用并可视化:
测试数据
验证集的数据型态比较不同,我为了使用ImageFolder在test1文件夹中又新增了一个test文件夹并且将图片都丢入其中,最后用ImageFolder打包。
当初有做什么样的图片变化,测试的时候一样要做,否则预测就不准确了:
接着就可以进行预测了,这边我们只取第一个batch的图片也就是16张图片,将其丢进神经网络模型后会获得一组数据 [ 16, 1 ],代表16张图片的预测结果,我们可以透过程序代码取得较大数值的维度,用来判断猫( 0 ) 还是狗 ( 1 )。
预测的程序代码如下:
最后结果可以看到,这次预测16张图片只有错2张图片~