0
点赞
收藏
分享

微信扫一扫

36、Pytorch之小土堆学习记录

钎探穗 2022-11-14 阅读 63


基本思想:花了两天时间把bilibil上小土堆的视频刷完了,简单记录一下 ,主要目的是想学习如何转模型,陆陆续续结合ncnn源码,如何实现onnx--->ncnn或者其它学习框架的模型转化,先来简单的demo在深入搞复杂的demo​​PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】_哔哩哔哩_bilibili​​

一、首先是搭建训练网络

(1)、网络模型

36、Pytorch之小土堆学习记录_python

 model_tudui.py

import torch.nn as nn
import torch
class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__init__()
self.model=nn.Sequential(
nn.Conv2d(3,32,(5,5),(1,1),2),#32@32*32
nn.MaxPool2d(2),#32@16*16
nn.Conv2d(32,32,(5,5),(1,1),2),#32@16*16
nn.MaxPool2d(2),#32@8*8
nn.Conv2d(32,64,(5,5),(1,1),2),#64@8*8
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(64*4*4, 64),
nn.Linear(64,10)
)
def forward(self,x):
output=self.model(x)
return output


if __name__== '__main__':
tudui=Tudui()
input=torch.ones((64,3,32,32))
output=tudui(input)
print(output.shape)

train_tudui.py

import torchvision
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from model_tudui import Tudui
from torch.utils.tensorboard import SummaryWriter


device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
train_data=torchvision.datasets.CIFAR10(root="./",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_data=torchvision.datasets.CIFAR10(root="./",train=False,transform=torchvision.transforms.ToTensor(),download=True)

train_dataloader=DataLoader(train_data,batch_size=64)
test_dataloader=DataLoader(test_data,batch_size=64)
test_data_size=len(test_dataloader)
writer=SummaryWriter("./log")

tudui=Tudui().to(device)
loss_fn=nn.CrossEntropyLoss()
loss_fn=loss_fn.to(device)
total_train_step=0
learning_rate=0.01
optimizer=torch.optim.SGD(tudui.parameters(),lr=learning_rate)

epoch=50
for i in range(epoch):
print("第{} 轮训练开始".format(i+1))
for data in train_dataloader:
img,target=data
img = img.to(device)
target = target.to(device)
output=tudui(img)
loss=loss_fn(output,target)

optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step=total_train_step+1
if total_train_step%100==0:
print("train {} loss {}".format(total_train_step,loss))
writer.add_scalar("train",loss,total_train_step)
test_loss=0
total_prec=0
with torch.no_grad():
for data in test_dataloader:
img, target = data
img=img.to(device)
target=target.to(device)
output = tudui(img)
accracy=(output.argmax(1)==target).sum()
total_prec=total_prec+accracy
loss = loss_fn(output, target)
test_loss=test_loss+loss
print("test prec {}".format(total_prec/test_data_size))
print("test loss {}".format(test_loss))
writer.add_scalar("test", test_loss, total_train_step)
if total_train_step%10==0:
torch.save(tudui,"{}.pt".format(i))
writer.close()

训练过程

"C:\Program Files\Python36\python.exe" G:/sxj731533730/sxj731533730/train_tudui.py
Files already downloaded and verified
Files already downloaded and verified
2022-01-15 10:25:59.932716: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library cudart64_101.dll
第1 轮训练开始
train 100 loss 2.2979342937469482
train 200 loss 2.285620927810669
train 300 loss 2.2694332599639893
.....
train 38800 loss 0.46276727318763733
train 38900 loss 0.2191564440727234
train 39000 loss 0.20267267525196075
train 39100 loss 0.1330123096704483
test prec 40.73248291015625
test loss 280.9912109375

Process finished with exit code 0

test_tudui.py

from PIL import Image
import torch
import torchvision
import cv2
from model_tudui import Tudui

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")



img=Image.open("dog.jpg")
tensorform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
torchvision.transforms.ToTensor()])
img = tensorform(img)
print(img.shape)
img = torch.reshape(img, [1, 3, 32, 32])

model = torch.load("49.pt")
model.to(device)
model.eval()
with torch.no_grad():
output = model(img.to(device))
print(output)
print(output.argmax(1))

测试图

36、Pytorch之小土堆学习记录_#include_02

36、Pytorch之小土堆学习记录_人工智能_03

 测试结果

"C:\Program Files\Python36\python.exe" G:/sxj731533730/sxj731533730/test_tudui.py
torch.Size([3, 32, 32])
tensor([[ 0.9691, -25.3604, 5.2494, 14.3558, 0.3240, 17.5721, -2.3385,
15.8048, -19.6210, -7.4380]], device='cuda:0')
tensor([5], device='cuda:0')

Process finished with exit code 0

onnx_tudui.py   参考官方手册: ​​torch.onnx — PyTorch master documentation​​

from model_tudui import Tudui
import torch
from PIL import Image
import torchvision

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

dummy_input = torch.ones(1, 3, 32, 32)
model = torch.load("49.pt")
model.to(device)
model.eval()
input_names = ['input']
output_names = ['output']
torch_out = torch.onnx._export(model, dummy_input.to(device), "49.onnx",verbose=True, input_names=input_names, output_names=output_names,opset_version=11)

使用netrion.app查看一下

36、Pytorch之小土堆学习记录_人工智能_04

onnxruntime_tudui.py推理一下

from model_tudui import Tudui
import torch
from PIL import Image
import torchvision
import onnxruntime as ort
img=Image.open("dog.jpg")
tensorform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
torchvision.transforms.ToTensor()])
img = tensorform(img)
print(img.shape)
img = torch.reshape(img, [1, 3, 32, 32])
ort_session = ort.InferenceSession("49.onnx")
input_name = ort_session.get_inputs()[0].name
result = ort_session.run([], {input_name: img.data.numpy()})
print(result[0])

测试结果

"C:\Program Files\Python36\python.exe" G:/sxj731533730/sxj731533730/onnxruntime_tudui.py
torch.Size([3, 32, 32])
[[ 0.96906763 -25.360426 5.249416 14.355831 0.3240289
17.572153 -2.3384833 15.804847 -19.621029 -7.4380264 ]]

Process finished with exit code 0

onnxruntime_cv_tudui.py

from model_tudui import Tudui
import torch
from PIL import Image
import torchvision
import onnxruntime as ort
import cv2
import numpy as np
from torch.autograd import Variable

img=cv2.imread("dog.jpg")
print(img.shape)
################################################## 实现了transform.Totensor
img=cv2.resize(img,(32,32))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # hwc rgb
img = np.transpose(img, (2, 0, 1)).astype(np.float32) # chw rgb
img[0, ...] = (img[0, ...]/255.0)
img[1, ...] = (img[1, ...]/255.0)
img[2, ...] = (img[2, ...]/255.0)

now_image1 = Variable(torch.from_numpy(img))
dummy_input = now_image1.unsqueeze(0)
################################################# 实现了transform.Totensor
# PIL 和 cv2 torch 的resize 不同 所以和c++ cv 处理生成结果就不同
#实际使用需要使用均值和方差进行图片预处理,然后在输出,这里只作为例子
ort_session = ort.InferenceSession("49.onnx")
input_name = ort_session.get_inputs()[0].name
result = ort_session.run([], {input_name: dummy_input.data.numpy()})
print(result[0])

测试结果

"C:\Program Files\Python36\python.exe" G:/sxj731533730/sxj731533730/swin_transformer_demo/onnxruntime_cv_tudui.py
(177, 248, 3)
[[ 3.113657 -23.358397 1.8361044 13.623332 0.7371707 16.093525
-4.442432 17.587536 -21.02534 -5.0484915]]

Process finished with exit code 0

转一下模型

D:\ncnn\buildMinGW\install\bin>onnx2ncnn.exe G:\sxj731533730\sxj731533730\49.onnx G:\sxj731533730\sxj731533730\49.param G:\sxj731533730\sxj731533730\49.bin

其中49.param的内容 ​​https://github.com/Tencent/ncnn/wiki/param-and-model-file-structure​​

7767517
10 10
Input input 0 1 input
Convolution Conv_0 1 1 input 11 0=32 1=5 11=5 2=1 12=1 3=1 13=1 4=2 14=2 15=2 16=2 5=1 6=2400
Pooling MaxPool_1 1 1 11 12 0=0 1=2 11=2 2=2 12=2 3=0 13=0 14=0 15=0 5=1
Convolution Conv_2 1 1 12 13 0=32 1=5 11=5 2=1 12=1 3=1 13=1 4=2 14=2 15=2 16=2 5=1 6=25600
Pooling MaxPool_3 1 1 13 14 0=0 1=2 11=2 2=2 12=2 3=0 13=0 14=0 15=0 5=1
Convolution Conv_4 1 1 14 15 0=64 1=5 11=5 2=1 12=1 3=1 13=1 4=2 14=2 15=2 16=2 5=1 6=51200
Pooling MaxPool_5 1 1 15 16 0=0 1=2 11=2 2=2 12=2 3=0 13=0 14=0 15=0 5=1
Flatten Flatten_6 1 1 16 17
InnerProduct Gemm_7 1 1 17 18 0=64 1=1 2=65536
InnerProduct Gemm_8 1 1 18 output 0=10 1=1 2=640

ncnn_tudui.cpp

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "net.h"
#include <iostream>
int main()
{
cv::Mat img = cv::imread("../dog.jpg");
int w = img.cols;
int h = img.rows;
ncnn::Mat in = ncnn::Mat::from_pixels_resize(img.data, ncnn::Mat::PIXEL_BGR2RGB, w, h, 32, 32);
const float norm_255[3] = {1/255.0f, 1/255.0f, 1/255.0f};
// in.substract_mean_normalize(mean_vals, std_vals);
in.substract_mean_normalize(0, norm_255);


ncnn::Net net;
net.load_param("../49.param");
net.load_model("../49.bin");

ncnn::Extractor ex = net.create_extractor();


ex.input("input", in);

ncnn::Mat feat;
ex.extract("output", feat);

for(int i=0;i<feat.w;i++)
std::cout<<feat[i]<<std::endl;
return 0;
}

测试结果

F:\trackgood\cmake-build-debug\trackgood.exe
3.11366
-23.3584
1.8361
13.6233
0.737176
16.0935
-4.44243
17.5875
-21.0253
-5.04849

Process finished with exit code 0

这里只是保证了转的onnx模型和c++模型输出是一致的,最后的结果并不能使用,主要是因为我训练的步数太少了,精度太差,预测并不准确,也可能是图片缩放的太小了

参考:

​​Home · Tencent/ncnn Wiki · GitHub​​

​​PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】_哔哩哔哩_bilibili​​

​​https://github.com/Tencent/ncnn/wiki/param-and-model-file-structure​​

举报

相关推荐

0 条评论