- 2024-08-29
-
回复了主题帖:
>>征集 | 使用 MCU,哪些问题最令你头大?
最头疼的是冷门产品资料不够完善,又存在bug的情况下,排查问题要人命,比如IIC通讯对起始时序要求特别严格,一不注意就踩坑
- 2024-07-09
-
回复了主题帖:
颁奖:嵌入式工程师AI挑战营(初阶),致敬敢于将边缘AI收入统治领域的你们
恭喜获奖大佬,俺们就蹭个板卡玩玩
- 2024-05-26
-
发表了主题帖:
#AI挑战营终点站 #rv1106数字识别模型部署及实战测试
前情概述
#AI挑战营第一站#基于Pytorch的卷积神经网络识别MNIST数据集-小白从零开始篇 https://bbs.eeworld.com.cn/thread-1278510-1-1.html
#AI挑战营第二站#Ubuntu环境下ONNX模型转换为RKNN模型 https://bbs.eeworld.com.cn/thread-1280304-1-1.html
【AI挑战营终点站】Luckfox Pico开发板开箱及初上手 https://bbs.eeworld.com.cn/thread-1282269-1-1.html
SDK部署
SDK要求的部署环境:Ubuntu22.04
部署过程此处省略一万字(主要是想偷懒),请参考官网教程执行https://wiki.luckfox.com/zh/Luckfox-Pico/Luckfox-Pico-SDK/
从gitee下载luyism大神的代码并解压,https://gitee.com/luyism/luckfox_rtsp_mnist
设置环境变量
export LUCKFOX_SDK_PATH=刚才解压后文件夹位置
创建一个build文件夹,并切换到文件夹内。
mkdir build
cd build
编译文件
cmake ..
make && make install
Application上传
编译后会生成luckfox_rtsp_mnist_dir文件夹,文件夹内应该有如下三个文件:
需要将此文件夹上传到Luckfox-pico,此处咨询了群里大神,使用sftp来传输,具体sftp使用教程可以根据此帖子学习下https://linuxstory.org/how-to-use-sftp-to-securely-transfer-files-with-a-remote-server/
这里简单点直接用微软自带的powershell工具来通过sftp协议上传,输入下面命令登录sftp,显示下面截图就证明访问成功了
sftp root@172.32.0.93
查看下本地目录位置
lpwd
查看下远程目录位置
pwd
切换到你自己想存放的位置,这里我放到了/usr下
cd /usr
先远程创建个文件夹,然后把luckfox_rtsp_mnist_dir文件夹上传到该目录
mkdir luckfox_rtsp_mnist_dir
put -r luckfox_rtsp_mnist_dir
退出sftp目录
exit
重新ssh登录开发板
ssh root@172.32.0.93
切换到刚才上传的文件夹目录,我这里漏掉了建立文件夹那一步,所以文件比较乱。
因为默认后台启动运行了rtsp服务会冲突,所以需要先结束掉原有应用。
RkLunch-stop.sh
运行应用,此处我调用的是model2
./luckfox_rtsp_mnist ./model/model2.rknn
使用VLC重新打开串流,调整镜头,使得数字准确清晰。
测试条件很简陋,大家将就看,不过提醒大家一点,光线条件对实测结果影响蛮大的,需要注意。实测4和9的识别准确率偏低,其他数字高点的能到70%多。
[localvideo]19c769da962491a6495870dd780c951a[/localvideo]
- 2024-05-25
-
上传了资料:
Luckfox Pico Max开发板buildroot版镜像文件
- 2024-05-19
-
发表了主题帖:
【AI挑战营终点站】Luckfox Pico开发板开箱及初上手
本帖最后由 爱吃鱼的加菲猫 于 2024-5-25 22:17 编辑
前面看了网友tobot的帖子,貌似对这个开发板具体型号有疑问,我这里就补充下,我们申请到的应该都是256MB内存且带256MB NAND FLASH的Luckfox Pico Max版本(也就是顶配)
这里也补充几张开箱照,
此处解释下为啥我们的是Max版本,仔细看芯片型号就会看出来,我们的是RV1106G3,参照下面表就明白配置了。
型号的秘密也藏在背面丝印,@吾妻思萌
红色框里可看出来,型号写的是Luckfox Pico Pro/Max,其实这里的原因是两个配置区别只有MCU内部集成的RAM大小,板子啥都是一样的,所以厂家就用了同一块PCB设计。两个型号区分方式是绿色框里QC标签,图里遮住了右侧露出了左侧256MB,那这个就是Max版。反之128MB就说明是Pro版本。
下面开始初步上手操作:
这里主要参照官网教程入个门,链接地址https://wiki.luckfox.com/zh/Luckfox-Pico/Luckfox-Pico-quick-start
安装驱动
下载并安装RK驱动助手 DriverAssitant,链接https://files.luckfox.com/wiki/Luckfox-Pico/Software/DriverAssitant_v5.12.zip,注意安装完成后要重启下电脑。
顺带也附件形式贴上来
官方镜像
官网提供了适配 LuckFox Pico 和 LuckFox Pico Mini A 的 SD 卡固件以及 LuckFox Pico Mini B 和 LuckFox Pico Plus/Pro/Max 的 SPI FLASH 固件两种,这里我把适配LuckFox Pico Max 的 SPI FLASH 固件贴上来,也省的大家再去找,而且官方用的百度网盘速度也贼慢(整整下载了两天两夜,谁让我没买会员呢)。
固件烧录
此处看了knv网友的帖子,为了避免后续推理部署遇到麻烦,直接烧录buildroot镜像,官网烧录工具为https://files.luckfox.com/wiki/Luckfox-Pico/Software/SocToolKit.zip,这里也传上来。
此处选择RV1106
把我上传的镜像包解压,并选择该文件夹,另外别忘记全选。
摄像头排线接到板子上,注意别插错方向,然后按住BOOT按键,用TYPE-C线接到电脑上后松手。
烧录软件会发现新设备
点击烧录
下载完成后自动重启,网络适配器里会出现一个RNDIS网卡
配置下网卡IP地址,其实是与开发板连接的电脑IP地址
可以ping通即可
通过ssh 或者telnet 访问
登录账号:root
登录密码:luckfox
静态IP地址:172.32.0.93
此处可以看到生成了rkipc.ini的文件,说明能Camera已经挂载成功
使用VLC拉流软件即可读取到实时画面,感觉网络有延迟。VLC也传上来吧,省的大家找了。
- 2024-05-09
-
回复了主题帖:
入围名单公布:嵌入式工程师AI挑战营(初阶),获RV1106 Linux 板+摄像头的名单
爱吃鱼的加菲猫 发表于 2024-5-8 18:16
个人信息已确认,领取板卡
个人信息已确认,领取板卡,可继续完成&分享挑战营第二站和第三站任务
- 2024-05-08
-
回复了主题帖:
入围名单公布:嵌入式工程师AI挑战营(初阶),获RV1106 Linux 板+摄像头的名单
个人信息已确认,领取板卡
- 2024-05-02
-
回复了主题帖:
【AI挑战营第二站】算法工程化部署打包成SDK
1、跟帖回复:什么是ONNX模型、RKNN模型
ONNX:是Open Neural Network Exchange的英文简称,中文意思为开放神经网络交换,是微软和Facebook提出用来表示深度学习模型的开放格式。所谓开放就是ONNX定义了一组和环境,平台均无关的标准格式,来增强各种AI模型的可交互性。换句话说,无论你使用何种训练框架训练模型(比如TensorFlow/Pytorch/OneFlow/Paddle),在训练完毕后你都可以将这些框架的模型统一转换为ONNX这种统一的格式进行存储,可以很方便的与他人分享并转化为其他各种格式模型。
NPU:是Neural network Processing Unit的英文简称,中文名字为神经网络处理器,用电路模拟人类的神经元和突触结构。与传统冯诺依曼架构的CPU相比,会有百倍以上的性能或能耗比提升。
RKNN,是Rockchip Neural Network的英文简称,是瑞芯微为了加速模型推理而基于自身NPU硬件架构定义的一套模型格式,使用该格式定义的模型在Rockchip NPU上可以获得更高的性能
2、以#AI挑战营第二站#为标题前缀,发帖分享ONNX模型转换成RKNN模型过程,包含环境部署、转换代码、解读代码,并附上RKNN模型。
#AI挑战营第二站#Ubuntu环境下ONNX模型转换为RKNN模型 https://bbs.eeworld.com.cn/thread-1280304-1-1.html
-
发表了主题帖:
#AI挑战营第二站#Ubuntu环境下ONNX模型转换为RKNN模型
本帖最后由 爱吃鱼的加菲猫 于 2024-5-2 17:45 编辑
背景信息
之前,【AI挑战营第一站】模型训练部分,我们已经完成了在PC上完成手写数字模型训练。但是想要最终部署到RV1106上,需要将第一阶段的ONNX模型,转为RKNN的模型,也就是算法工程化部署打包成SDK,这样才能在RV1106的NPU加载使用。
专有名词
ONNX:是Open Neural Network Exchange的英文简称,中文意思为开放神经网络交换,是微软和Facebook提出用来表示深度学习模型的开放格式。所谓开放就是ONNX定义了一组和环境,平台均无关的标准格式,来增强各种AI模型的可交互性。换句话说,无论你使用何种训练框架训练模型(比如TensorFlow/Pytorch/OneFlow/Paddle),在训练完毕后你都可以将这些框架的模型统一转换为ONNX这种统一的格式进行存储,可以很方便的与他人分享并转化为其他各种格式模型。
NPU:是Neural network Processing Unit的英文简称,中文名字为神经网络处理器,用电路模拟人类的神经元和突触结构。与传统冯诺依曼架构的CPU相比,会有百倍以上的性能或能耗比提升。
RKNN,是Rockchip Neural Network的英文简称,是瑞芯微为了加速模型推理而基于自身NPU硬件架构定义的一套模型格式,使用该格式定义的模型在Rockchip NPU上可以获得更高的性能,文件以.rknn后缀结尾。
RKNN toolkit,是瑞芯微为用户提供在 PC、 Rockchip NPU 平台上进行模型转换、推理和性能评估的 开发套件,用户通过该工具提供的 Python 接口可以便捷地完成模型转换、量化功能、模型推理、性能和内存评估、量化精度分析、模型加密等功能。
开发环境
64位Windows10系统
老黄家的显卡,已安装CUDA 12.2.79
PyCharm 社区版2024.1
环境搭建
注意RV1106需要用RKNN-Toolkit2,官方链接https://github.com/airockchip/rknn-toolkit2
适用的芯片平台如下:
RK3566/RK3568 Series
RK3588 Series
RK3576 Series
RK3562 Series
RV1103/RV1106
RK2118
目前支持的系统如下:
Ubuntu 18.04 python 3.6/3.7
Ubuntu 20.04 python 3.8/3.9
Ubuntu 22.04 python 3.10/3.11
当前最新版本:v2.0.0-beta0
这里大家可以看到,开发环境只支持ubuntu,无奈电脑上重新安装了个Ubuntu
安装Conda
下载安装包
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-4.6.14-Linux-x86_64.sh
接着可以安装miniconda
chmod 777 Miniconda3-4.6.14-Linux-x86_64.sh
bash Miniconda3-4.6.14-Linux-x86_64.sh
一路回车,最后输入yes
最后回车,确认安装位置
输入conda -V命令,查看下conda是否安装成功
Conda内创建Python开发环境
这里在Conda内创建了一个名为toolkit2,Python3.10的环境,后续都在次环境内执行
conda create -n toolkit2 python=3.10
切换到对应环境内
conda activate toolkit2
下载RKNN-Toolkit2相关仓库文件
新建rv1106文件夹
mkdir rv1106
切换到文件夹内
cd rv1106
从仓库拉取文件,注意要提前安装好git
git clone https://github.com/airockchip/rknn-toolkit2.git --depth 1
安装依赖库及RKNN-Toolkit2
切换到目录内
cd rv1106/rknn-toolkit2/rknn-toolkit2
选择对应配置文件并安装,这里我的环境是python 3.10,注意要根据packages目录下文件名字
pip install -r packages/requirements_cp310-2.0.0b0.txt
这里需要联网下载很多依赖包,需要慢慢等。
根据不同的 python 版本及处理器架构,选择不同的 wheel 安装包文件,注意此处也要根据前面文件夹目录下文件
pip install packages/rknn_toolkit2-2.0.0b0+9bab5682-cp310-cp310-linux_x86_64.whl
执行完后验证下是否安装成功
下载 rknn_model_zoo
这是瑞芯微官方的用于转换模型的工具,你可以理解为里面是很多实例脚本,里面有很多转换示例,转换代码我们可以借鉴里面的。
rv1106目录下执行下面命令:
git clone https://github.com/airockchip/rknn_model_zoo.git
转换模型
找到我们训练营第一站训练出来的ONNX文件,并放在我们新建的文件夹目录下面。
文件夹目录按照我这个准备下
我顺带把图片素材也上传上来
转换遇到了错误,因为用的rknn-toolkit2是最新的2.0.0版本,对ONNX模型要求最低19,我这里提示用的17版本,所以还需要重新把模型转换为19版本的
这里我借用网友qiao---的新版本onnx文件
转换代码
from rknn.api import RKNN
# Create RKNN object
rknn = RKNN(verbose=True)
# pre-process config
print('--> config model')
rknn.config(target_platform='rv1106', mean_values=[[28]], std_values=[[28]])
print('done')
# Load model
print('--> Loading model')
ret = rknn.load_onnx(model='./mnist.onnx')
if ret != 0:
print('Load model failed!')
exit(ret)
print('done')
rknn.build(do_quantization=True, dataset='./data.txt') # 构建RKNN模型,可选参数量化
if ret != 0:
print('Build model failed!')
exit(ret)
print('done')
ret = rknn.export_rknn('./mnist.rknn') # 导出RKNN模型文件
if ret != 0:
print('Export rknn model failed!')
exit(ret)
print('done')
# 释放 RKNN 对象
rknn.release()
- 2024-04-25
-
回复了主题帖:
#AI挑战营第一站#基于PyTorch,在PC上完成MNIST手写数字识别模型训练
wangerxian 发表于 2024-4-24 17:22
那挺快的,我用CPU训练6轮,快十分钟了。
我用CPU训练时候,直接占用率拉满,电脑最好啥事都别干,GPU时候还可以正常使用
- 2024-04-23
-
回复了主题帖:
#AI挑战营第一站#基于Pytorch的卷积神经网络识别MNIST数据集-小白从零开始篇
前几天参照网友教程,我是Anaconda Prompt终端命令下进行的,在生成模型文件大小有问题,别人都是MB级别,我的是KB,估计是有问题,今晚又折腾了下,参照网友wangerxian帖子https://bbs.eeworld.com.cn/thread-1278516-1-1.html操作,先安装了PyCharm,然后再执行py。
执行的代码直接copy网友knv的,用GPU参与训练的,GPU占有率大概能到45%左右,CPU几乎跑满了。
生成文件如下:
文件大小应该是对了,跟knv生成的模型大小基本一致。
接下来参照其他网友的执行看看:
1、新建个工程
环境配置参照上面图片,Path to conda那里需要选择你Anaconda安装目录,别搞错了。Environment选择你生成的虚拟python环境,要提前在Prompt里面安装好相关包文件。
2、新建Python文件
①位置工程文件夹上右键,②新建,③选择Python文件
输入个文件名
把代码拷贝粘贴进来,然后点开左下角终端按钮
执行python文件
文件上右键,选择运行
执行结果:
pt文件生成了,但是转onnx时候报错,也不知道啥情况,有可能跟软件版本有关。
再来试试其他GPU训练的代码:
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as Data
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
from torchsummary import summary
import time
# 创建神经网络
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
)
self.layer2 = nn.Sequential(
nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2)
)
self.output_layer = nn.Linear(32*7*7, 10)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = x.reshape(x.size(0), -1)
output = self.output_layer(x)
return output
# 超参数
EPOCH = 2
BATCH_SIZE = 100
LR = 0.001
DOWNLOAD = True # 若已经下载mnist数据集则设为False
# 下载mnist数据
train_data = datasets.MNIST(
root='./data', # 保存路径
train=True, # True表示训练集,False表示测试集
transform=transforms.ToTensor(), # 将0~255压缩为0~1
download=DOWNLOAD
)
# 旧的写法
print(train_data.train_data.size())
print(train_data.train_labels.size())
# 新的写法
print(train_data.data.size())
print(train_data.targets.size())
# 打印部分数据集的图片
for i in range(2):
print(train_data.targets[i].item())
plt.imshow(train_data.data[i].numpy(), cmap='gray')
plt.show()
# DataLoader
train_loader = Data.DataLoader(
dataset=train_data,
batch_size=BATCH_SIZE,
shuffle=True,
num_workers=2
)
# 如果train_data下载好后,test_data也就下载好了
test_data = datasets.MNIST(
root='./data',
train=False
)
print(test_data.data.size())
print(test_data.targets.size())
# 新建网络
cnn = CNN()
# 将神经网络移到GPU上
cnn.cuda()
print(cnn)
# 查看网络的结构
model = CNN()
if torch.cuda.is_available():
model.cuda()
summary(model, input_size=(1,28,28))
# 优化器
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)
# 损失函数
loss_func = nn.CrossEntropyLoss()
# 为了节约时间,只使用测试集的前2000个数据
test_x = Variable(
torch.unsqueeze(test_data.data, dim=1),
volatile=True
).type(torch.FloatTensor)[:2000]/255 # 将将0~255压缩为0~1
test_y = test_data.targets[:2000]
# # 使用所有的测试集
# test_x = Variable(
# torch.unsqueeze(test_data.test_data, dim=1),
# volatile=True
# ).type(torch.FloatTensor)/255 # 将将0~255压缩为0~1
# test_y = test_data.test_labels
# 将测试数据移到GPU上
test_x = test_x.cuda()
test_y = test_y.cuda()
# 开始计时
start = time.time()
# 训练神经网络
for epoch in range(EPOCH):
for step, (batch_x, batch_y) in enumerate(train_loader):
# 将训练数据移到GPU上
batch_x = batch_x.cuda()
batch_y = batch_y.cuda()
output = cnn(batch_x)
loss = loss_func(output, batch_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 每隔50步输出一次信息
if step%50 == 0:
test_output = cnn(test_x)
# 将预测结果移到GPU上
predict_y = torch.max(test_output, 1)[1].cuda().data.squeeze()
accuracy = (predict_y == test_y).sum().item() / test_y.size(0)
print('Epoch', epoch, '|', 'Step', step, '|', 'Loss', loss.data.item(), '|', 'Test Accuracy', accuracy)
# 结束计时
end = time.time()
# 训练耗时
print('Time cost:', end - start, 's')
# 预测
test_output = cnn(test_x[:100])
# 为了将CUDA tensor转化为numpy,需要将数据移回CPU上
# 否则会报错:TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.
predict_y = torch.max(test_output, 1)[1].cpu().data.numpy().squeeze()
real_y = test_y[:100].cpu().numpy()
print(predict_y)
print(real_y)
# 打印预测和实际结果
for i in range(10):
print('Predict', predict_y[i])
print('Real', real_y[i])
plt.imshow(test_data.data[i].numpy(), cmap='gray')
plt.show()
执行后报错,
这里可以看到是没有torchsummary包,通过conda尝试,发现找不到这个包,无奈只能用pip来安装,
pip install torchsummary
再次执行,注意,如果你已经执行下载过mnist数据集,则39行为false,执行后这里会打开图片样本。
关闭图片窗口后会报错,搞不定了,继续换其他代码试试。
这里采用luyism的代码试试
https://bbs.eeworld.com.cn/thread-1278192-1-1.html
这里提示报错,原因是没安装onnxruntime包,在conda下安装下再次尝试可以生成模型文件,
这里尝试下qiao--网友的代码,
# 导包
import torch
import torch.nn as nn # 神经网络
import torch.optim as optim # 定义优化器
from torchvision import datasets, transforms # 数据集 transforms完成对数据的处理
# 定义超参数
input_size = 28 * 28 # 输入大小
hidden_size = 512 # 隐藏层大小
num_classes = 10 # 输出大小(类别数)
batch_size = 100 # 批大小
learning_rate = 0.001 # 学习率
num_epochs = 10 # 训练轮数
# 加载 MNIST 数据集
train_dataset = datasets.MNIST(root='../data/mnist', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='../data/mnist', train=False, transform=transforms.ToTensor(), download=True)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True) # 一批数据为100个
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)
# 定义 MLP 网络
class MLP(nn.Module):
# 初始化方法
# input_size 输入数据的维度
# hidden_size 隐藏层的大小
# num_classes 输出分类的数量
def __init__(self, input_size, hidden_size, num_classes):
# 调用父类的初始化方法
super(MLP, self).__init__()
# 定义第1个全连接层
self.fc1 = nn.Linear(input_size, hidden_size)
# 定义ReLu激活函数
self.relu = nn.ReLU()
# 定义第2个全连接层
self.fc2 = nn.Linear(hidden_size, hidden_size)
# 定义第3个全连接层
self.fc3 = nn.Linear(hidden_size, num_classes)
def forward(self, x):
# 将输入张量展平为向量
x = x.view(x.size(0), -1)
out = self.fc1(x)
out = self.relu(out)
out = self.fc2(out)
out = self.relu(out)
out = self.fc3(out)
return out
# 实例化 MLP 网络
model = MLP(input_size, hidden_size, num_classes)
# 现在我们已经定义了 MLP 网络并加载了 MNIST 数据集,接下来使用 PyTorch 的自动求导功能和优化器进行训练。首先,定义损失函数和优化器;然后迭代训练数据并使用优化器更新网络参数。
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
# CrossEntropyLoss = Softmax + log + nllloss
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# optimizer = optim.SGD(model.parameters(),0.2)
# 训练网络
# 外层for循环控制训练的次数
# 内层for循环控制从DataLoader中循环读取数据
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = images.reshape(-1, 28 * 28) # 将images转换成向量
outputs = model(images) # 将数据送到网络中
loss = criterion(outputs, labels) # 计算损失
optimizer.zero_grad() # 首先将梯度清零
loss.backward() # 反向传播
optimizer.step() # 更新参数
if (i + 1) % 100 == 0:
print(f'Epoch [{epoch + 1}/{num_epochs}],Step[{i + 1}/{len(train_loader)}],Loss:{loss.item():.4f}')
# 最后,我们可以在测试数据上评估模型的准确率:
# 测试网络
with torch.no_grad():
correct = 0
total = 0
# 从test_loader中循环读取测试数据
for images, labels in test_loader:
# 将images转换成向量
images = images.reshape(-1, 28 * 28)
# 将数据传送到网络
outputs = model(images)
# 取出最大值对应的索引 即预测值
_, predicted = torch.max(outputs.data, 1) # 返回一个元组:第一个为最大值,第二个是最大值的下标
# 累加labels数量 labels为形状为(batch_size,1)的矩阵,取size(0)就是取出batch_size的大小(该批的大小)
total += labels.size(0)
# 预测值与labels值对比 获取预测正确的数量
correct += (predicted == labels).sum().item()
# 打印最终的准确率
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total}%')
# 保存模型
# 保存模型的状态字典
torch.save(model.state_dict(), 'mnist.pth')
model.load_state_dict(torch.load('mnist.pth'))
# 将模型设置为评估模式(如果需要)
model.eval()
#导出为onnx模型
input = torch.randn(1, 28, 28)
torch.onnx.export(model, input, "mnist.onnx", verbose=True)
执行结果如下;
我发现大家生成的模型文件差别挺大的,这里模型准确率可以到98%了,10轮训练。
-
回复了主题帖:
#AI挑战营第一站#基于Pytorch的卷积神经网络识别MNIST数据集-小白从零开始篇
nmg 发表于 2024-4-22 10:09
好像差距是挺大的啊,刚随意看了下,他们上传的同格式的,都是M级别大小的
是的,我觉得也有问题,晚上有空再折腾看看
- 2024-04-21
-
回复了主题帖:
免费申请:幸狐 RV1106 Linux 开发板(带摄像头),助力AI挑战营应用落地
本帖最后由 爱吃鱼的加菲猫 于 2024-4-21 17:07 编辑
#AI挑战营第一站#基于Pytorch的卷积神经网络识别MNIST数据集-小白从零开始篇
https://bbs.eeworld.com.cn/thread-1278510-1-1.html
预期应用:手写数字识别,并所写所得显示在屏幕上,类似手写板
-
回复了主题帖:
【AI挑战营第一站】模型训练:在PC上完成手写数字模型训练,免费申请RV1106开发板
本帖最后由 爱吃鱼的加菲猫 于 2024-4-21 17:07 编辑
1.用自己的语言描述,模型训练的本质是什么,训练最终结果是什么
答:模型训练的本质是调整内部参数的集合,从而可以最大程度地拟合给定的数据。模型本质上是一种数学函数,比如此次挑战赛手写识别,它接收手写数字的图像作为输入,并输出对应的数字标签。 模型内部有许多参数,这些参数控制着模型对输入图像的处理方式。 模型训练实际上是在调整这些参数,使得模型能够正确地将输入图像映射到正确的数字标签上。
2.PyTorch是什么?目前都支持哪些系统和计算平台?
答:PyTorch是一个深度学习的框架和工具集合,它是由Facebook的AI研究团队开发并公开出来的,目前是应用最广泛的深度学习框架。
PyTorch支持主流的Windows、Linux、Mac等系统,可以看下图。计算平台既可以用CPU(牙膏厂的支持会更好点)、GPU(主要是老黄家的CUDA平台),也能够在云平台上运行,包括 Amazon Web Services、Google Cloud 和 Microsoft Azure。
3.动手实践: #AI挑战营第一站#基于Pytorch的卷积神经网络识别MNIST数据集-小白从零开始篇
-
回复了主题帖:
#AI挑战营第一站#基于Pytorch的卷积神经网络识别MNIST数据集-小白从零开始篇
感觉我的模型有点问题,大小跟大家的相差挺多
-
发表了主题帖:
#AI挑战营第一站#基于Pytorch的卷积神经网络识别MNIST数据集-小白从零开始篇
本帖最后由 爱吃鱼的加菲猫 于 2024-4-21 16:30 编辑
作为一个AI领域纯纯的小白,想要用Pytorch基于MNIST数据集训练个卷积网络模型,本帖子也作为我的学习log吧,高手们轻点拍。
先上本人电脑配置:
CPU:Intel(R) Core(TM) i5-4460 CPU @ 3.20GHz 3.20 GHz 四核四线程
GPU:NVIDIA GeForce GTX 750 Ti(未装CUDA)
RAM:8G
Windows 10 专业版
Python 3.12.1
搭建CUDA环境:
cmd命令行内输入nvidia-smi.exe,查看本机显卡驱动版本及可用的CUDA版本。
这里要注意,Pytorch对CUDA版本有要求,不能乱装,所以得到官网看看匹配的版本。
https://pytorch.org/get-started/locally/
这里可以看到,最新稳定版本的PyTorch能支持到CUDA12.1版本。
把我参考的安装教程链接贴上来,具体大家可以照着操作。
CUDA官网下载链接:https://developer.nvidia.com/cuda-toolkit-archive
根据自己系统进行选择,下载安装包。
下载完参照教程双击安装即可,接下来确认下环境变量。
cmd命令行里输入nvcc -version命令查看软件版本。
安装Anaconda
参考安装教程:https://blog.csdn.net/MCYZSF/article/details/116525159
anaconda是一个集成的工具软件,管理它安装Pytorch会很方便https://www.anaconda.com/
再来个GPU版本使用清华源的安装教程。https://cloud.tencent.com/developer/article/2405758
教程二https://www.zhihu.com/tardis/zm/art/681417713?source_id=1005
开始菜单栏找到Anaconda Prompt,我前面创建了虚拟环境名字叫pytorch,输入python,输入activate pytorch切换环境,输入import torch后回车,再输入torch.cuda.is_available()回车,
如果返回True,则证明环境已经配置好。
模型训练
接下来就可以正式开始模型训练工作了,这里我参考的实现是下面的教程,非常详细。
https://blog.csdn.net/qq_45588019/article/details/120935828
教程二:https://zhuanlan.zhihu.com/p/137571225
导入相关包文件
import torch
import torchvision
from torch.utils.data import DataLoader
引入MNIST数据集
定义超参数
n_epochs = 3
batch_size_train = 64
batch_size_test = 1000
learning_rate = 0.01
momentum = 0.5
log_interval = 10
random_seed = 1
torch.manual_seed(random_seed)
下载获取数据集(训练集及测试集),并用Dataloader 包起来,即载入数据集
train_loader = torch.utils.data.DataLoader(
torchvision.datasets.MNIST('./data/', train=True, download=True,
transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
(0.1307,), (0.3081,))
])),
batch_size=batch_size_train, shuffle=True)
test_loader = torch.utils.data.DataLoader(
torchvision.datasets.MNIST('./data/', train=False, download=True,
transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
(0.1307,), (0.3081,))
])),
batch_size=batch_size_test, shuffle=True)
运行上面的程序后,会自动将数据集下载到目录下的data文件夹。
展示MNIST数据集(如果要直接训练,这步可以忽略)
首先看看测试数据有啥。
examples = enumerate(test_loader)
batch_idx, (example_data, example_targets) = next(examples)
print(example_targets)
print(example_data.shape)
安装相关包文件,在Anaconda Prompt下执行以下命令:
conda install matplotlib
举例展示6幅图,包含图片内容和标签。
fig = plt.figure()
for i in range(12):
plt.subplot(3, 4, i+1)
plt.tight_layout()
plt.imshow(train_dataset.train_data[i], cmap='gray', interpolation='none')
plt.title("Labels: {}".format(train_dataset.train_labels[i]))
plt.xticks([])
plt.yticks([])
plt.show()
构建模型
此处使用两个2d卷积层,然后是两个全连接(或线性)层。作为激活函数,我们将选择整流线性单元(简称ReLUs),作为正则化的手段,我们将使用两个dropout层。
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
self.conv2_drop = nn.Dropout2d()
self.fc1 = nn.Linear(320, 50)
self.fc2 = nn.Linear(50, 10)
def forward(self, x):
x = F.relu(F.max_pool2d(self.conv1(x), 2))
x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
x = x.view(-1, 320)
x = F.relu(self.fc1(x))
x = F.dropout(x, training=self.training)
x = self.fc2(x)
return F.log_softmax(x)
实例化模型
network = Net()
初始化网络及优化器
criterion = torch.nn.CrossEntropyLoss() # 交叉熵损失
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate, momentum=momentum) # lr学习率,momentum冲量
定义训练及测试轮
Step1:前馈(forward propagation)
Step2:反馈(backward propagation)
Step3:更新(update)
训练轮代码:
def train(epoch):
running_loss = 0.0 # 这整个epoch的loss清零
running_total = 0
running_correct = 0
for batch_idx, data in enumerate(train_loader, 0):
inputs, target = data
optimizer.zero_grad()
# forward + backward + update
outputs = model(inputs)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()
# 把运行中的loss累加起来,为了下面300次一除
running_loss += loss.item()
# 把运行中的准确率acc算出来
_, predicted = torch.max(outputs.data, dim=1)
running_total += inputs.shape[0]
running_correct += (predicted == target).sum().item()
if batch_idx % 300 == 299: # 不想要每一次都出loss,浪费时间,选择每300次出一个平均损失,和准确率
print('[%d, %5d]: loss: %.3f , acc: %.2f %%'
% (epoch + 1, batch_idx + 1, running_loss / 300, 100 * running_correct / running_total))
running_loss = 0.0 # 这小批300的loss清零
running_total = 0
running_correct = 0 # 这小批300的acc清零
完整代码:
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as Data
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
from torchsummary import summary
import time
# 创建神经网络
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
)
self.layer2 = nn.Sequential(
nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2)
)
self.output_layer = nn.Linear(32*7*7, 10)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = x.reshape(x.size(0), -1)
output = self.output_layer(x)
return output
# 超参数
EPOCH = 2
BATCH_SIZE = 100
LR = 0.001
DOWNLOAD = False # 若已经下载mnist数据集则设为False
# 下载mnist数据
train_data = datasets.MNIST(
root='./data', # 保存路径
train=True, # True表示训练集,False表示测试集
transform=transforms.ToTensor(), # 将0~255压缩为0~1
download=DOWNLOAD
)
# 旧的写法
print(train_data.train_data.size())
print(train_data.train_labels.size())
# 新的写法
print(train_data.data.size())
print(train_data.targets.size())
# 打印部分数据集的图片
for i in range(2):
print(train_data.targets[i].item())
plt.imshow(train_data.data[i].numpy(), cmap='gray')
plt.show()
# DataLoader
train_loader = Data.DataLoader(
dataset=train_data,
batch_size=BATCH_SIZE,
shuffle=True,
num_workers=2
)
# 如果train_data下载好后,test_data也就下载好了
test_data = datasets.MNIST(
root='./data',
train=False
)
print(test_data.data.size())
print(test_data.targets.size())
# 新建网络
cnn = CNN()
# 将神经网络移到GPU上
cnn.cuda()
print(cnn)
# 查看网络的结构
model = CNN()
if torch.cuda.is_available():
model.cuda()
summary(model, input_size=(1,28,28))
# 优化器
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)
# 损失函数
loss_func = nn.CrossEntropyLoss()
# 为了节约时间,只使用测试集的前2000个数据
test_x = Variable(
torch.unsqueeze(test_data.data, dim=1),
volatile=True
).type(torch.FloatTensor)[:2000]/255 # 将将0~255压缩为0~1
test_y = test_data.targets[:2000]
# # 使用所有的测试集
# test_x = Variable(
# torch.unsqueeze(test_data.test_data, dim=1),
# volatile=True
# ).type(torch.FloatTensor)/255 # 将将0~255压缩为0~1
# test_y = test_data.test_labels
# 将测试数据移到GPU上
test_x = test_x.cuda()
test_y = test_y.cuda()
# 开始计时
start = time.time()
# 训练神经网络
for epoch in range(EPOCH):
for step, (batch_x, batch_y) in enumerate(train_loader):
# 将训练数据移到GPU上
batch_x = batch_x.cuda()
batch_y = batch_y.cuda()
output = cnn(batch_x)
loss = loss_func(output, batch_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 每隔50步输出一次信息
if step%50 == 0:
test_output = cnn(test_x)
# 将预测结果移到GPU上
predict_y = torch.max(test_output, 1)[1].cuda().data.squeeze()
accuracy = (predict_y == test_y).sum().item() / test_y.size(0)
print('Epoch', epoch, '|', 'Step', step, '|', 'Loss', loss.data.item(), '|', 'Test Accuracy', accuracy)
# 结束计时
end = time.time()
# 训练耗时
print('Time cost:', end - start, 's')
# 预测
test_output = cnn(test_x[:100])
# 为了将CUDA tensor转化为numpy,需要将数据移回CPU上
# 否则会报错:TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.
predict_y = torch.max(test_output, 1)[1].cpu().data.numpy().squeeze()
real_y = test_y[:100].cpu().numpy()
print(predict_y)
print(real_y)
# 打印预测和实际结果
for i in range(10):
print('Predict', predict_y[i])
print('Real', real_y[i])
plt.imshow(test_data.data[i].numpy(), cmap='gray')
plt.show()
训练结果如下:
用时100s左右,精度可以到0.97了,足够手写识别。
保存并转换成ONNX模型
# 保存模型的状态字典
torch.save(model.state_dict(), 'mnist.pth')
model.load_state_dict(torch.load('mnist.pth'))
# 将模型设置为评估模式(如果需要)
model.eval()
#导出为onnx模型
input = torch.randn(1, 28, 28)
torch.onnx.export(model, input, "mnist.onnx", verbose=True)
-
回复了主题帖:
(已颁奖)嵌入式工程师AI挑战营(初阶):基于RV1106,动手部署手写数字识别落地
今晚开干,争取尽快完成第一站任务
- 2024-03-07
-
上传了资料:
【得捷电子Follow me第4期】任务源代码汇总
- 2024-03-03
-
回复了主题帖:
得捷电子Follow me第4期】成果展示帖
任务总结视频:
(PS:请原谅视频里我穿着睡衣,这活真的是忙活了一晚上才搞定,搞技术的玩视频剪辑真的是不咋溜)
[localvideo]7451cd2c0573004689781b1136b551b9[/localvideo]
- 2024-02-26
-
回复了主题帖:
得捷电子Follow me第4期】成果展示帖
秦天qintian0303 发表于 2024-2-26 09:16
Follow me是真正的实践教程,这类活动其实可以好好多办点
非常感谢Digi-key和EE举办的这个活动,对于新手来说非常棒,真正的能从自己动手中学到东西。
平时开发板那种买来都是现成代码,单纯编译跑一下没任何意义,只有在自己钻研,遇到问题排除问题过程中才能更快成长。