Tensorboard是Pytorch提供的一个可视化包,引入包:
from torch.utils.tensorboard import SummaryWriter
使用以下方式调用:
writer = SummaryWriter("logs")
使用以下方法调用:
writer.add_image("img",img_cv2,1,dataformats='HWC')
writer.add_scalar("scaler",1,1)
在终端输入tensorboard --logdir=logs即可运行,其中–logdir指定log目录。
from torch.utils.tensorboard import SummaryWriter
import cv2
img_path = r"C:\Users\guoyiyu\Desktop\chart_yolo-obj.png"
img_cv2= cv2.imread(img_path)
print(img_cv2.shape)
writer = SummaryWriter("logs")
#显示图片
writer.add_image("img",img_cv2,1,dataformats='HWC')
#显示数
for i in range(100):
writer.add_scalar("y=x",i,i)
writer.close()
pytorch中的transforms模块中包含了很多种对图像数据进行变换的函数。引入包:
from torchvision import transforms
使用以下方式调用:
trans_tensor = transforms.ToTensor() #实例化对象
img_tensor = trans_tensor(img_cv2) #因为有__call__函数,所以对象可以像函数一样调用
如果图片有三个通道,则参数为([R1,G1,B1],[R2,G2,B2]),如果图片只有一个通道,则参数为(W1,W2)。计算方法是:
O U T = I N − W 1 W 2 OUT = \frac{IN-W1}{W2} OUT=W2IN−W1
使用以下方式调用:
trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm = trans_norm(img_tensor) #转换后还是张量
注意该函数只能裁剪PIL格式的图片
使用以下方式调用:
img_resize = Image.fromarray(img_cv2) #cv2 -> PIL
trans_resize = transforms.Resize((512,512))
img_resize = trans_resize(img_resize)
img_resize = np.array(img_resize) #PIL -> cv2
使用以下方式调用:
trans_resize = transforms.Resize((512,512))
trans_tensor = transforms.ToTensor()
trans_compose = transforms.Compose([trans_resize, trans_tensor])
img_compose = trans_compose(Image.fromarray(img_cv2)) #PIL -> Resize ->Tensor
#transforms学习
from numpy.core.defchararray import array
from torchvision import transforms
import cv2
import numpy as np
from PIL import Image
img_path = r"C:\Users\guoyiyu\Desktop\123.jpg"
img_cv2= cv2.imread(img_path)
print(type(img_cv2))
print(img_cv2)
cv2.imshow("img_array",img_cv2)
cv2.waitKey(0)
#ToTensor
trans_tensor = transforms.ToTensor()
img_tensor = trans_tensor(img_cv2)
print(type(img_tensor))
print(img_tensor)
#Normalize
trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm = trans_norm(img_tensor)
img_array = img_norm.numpy()
print(img_array.shape) #CHW
img_array = np.transpose(img_array,(1,2,0)) #转成成通道HWC才可以用imshow显示
cv2.imshow("img_array",img_array)
cv2.waitKey(0)
#Resize
trans_resize = transforms.Resize((512,512))
img_resize = Image.fromarray(img_cv2) #cv2 -> PIL
img_resize = trans_resize(img_resize)
img_resize = np.array(img_resize) #PIL -> cv2
print(type(img_resize))
cv2.imshow("resize",img_resize)
cv2.waitKey(0)
#Compose
trans_compose = transforms.Compose([trans_resize, trans_tensor])
img_compose = trans_compose(Image.fromarray(img_cv2)) #PIL -> Resize ->Tensor
print(type(img_compose))
pytorch中的dataset模块用于获取并处理数据集,引入包:
import torchvision
使用以下方式调用
test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, download=True, transform=torchvision.transforms.ToTensor())
import torchvision
#train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, download=True)
test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, download=True, transform=torchvision.transforms.ToTensor())
#test_Set
print(test_set[0]) #打印第一个数据
img, _ = test_set[0]
print(img.shape)
pytorch中的dataloader模块用于批量加载数据集,引入包:
import torch.utils.data as Data
使用以下方式调用:
test_loader = Data.DataLoader(dataset=test_set, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
import torch.utils.data as Data
from torch.utils.tensorboard import SummaryWriter
test_loader = Data.DataLoader(dataset=test_set, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
#test_loader
writer = SummaryWriter("log")
for epoch in range(2):
step = 0
for data in test_loader:
imgs, _ = data
writer.add_images("epoch:{}".format(epoch), imgs, step)
step = step+1
writer.close()
效果如下:
Pytorch中的nn模块提供了搭建神经网络所需的包。引入包:
from torch import nn
继承nn.Module类,并进行重写。举例如下:
from torch import nn
import torch
class test_nn(nn.Module):
def __init__(self) -> None:
super().__init__()
def forward(self, input):
output = input + 1
return output
test_nn = test_nn()
input = torch.tensor(1.0)
output = test_nn(input)
print(output)
格式:nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)
例子:self.conv1 = nn.Conv2d(inplanes, planes[0], kernel_size=1,stride=1, padding=0, bias=False)
[N, C, H, W]
(其中N表示输入样本的数量; H表示特征图的高;W表示特征图的宽; C表示特征图的通道数。)中的C
了,即输入张量的通道数。这个形参是确定权重等可学习参数所必需的。padding = 1
为例,若原始图像大小为32x32
,那么padding后的图像大小就变成了34x34
,而不是33x33
。一个有序的容器,神经网络模块将按照在传入构造器的顺序依次被添加到计算图中执行,同时以神经网络模块为元素的有序字典也可以作为传入参数。
示例代码如下:
import torch
from torch import nn
import torch.utils.data as Data
import torchvision
test_dataset = torchvision.datasets.CIFAR10(root="\data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
test_dataloader = Data.DataLoader(dataset=test_dataset, batch_size=64, shuffle=True, num_workers=0, drop_last=True)
class test_nn(nn.Module):
def __init__(self):
super().__init__()
self.linear = nn.Linear(196608,10)
def forward(self, input):
output = self.linear(input)
return output
test_nn = test_nn()
for data in test_dataloader:
img, _ = data
print(img.shape)
img_fatten = torch.flatten(img) #展平
print(img_fatten.shape)
img_linear = test_nn(img_fatten)
print(img_linear.shape)
示例代码如下:
import torch
import torch.nn as nn
#L1loss
input = torch.tensor([1, 2, 3], dtype=torch.float32)
target = torch.tensor([1, 2, 5], dtype=torch.float32)
input = torch.reshape(input, (1,1,1,-1))
target = torch.reshape(target,(1,1,1,-1))
loss_L1los = nn.L1Loss(reduction="sum")
result_L1loss = loss_L1los(input, target)
print(result_L1loss)
#CrossEntropyLoss
input = torch.tensor([0.1, 0.8, 0.1])
target = torch.tensor([1])
input = torch.reshape(input, (1,-1)) #-1表示自适应
loss_cross = nn.CrossEntropyLoss()
result_cross = loss_cross(input, target)
print(result_cross)
在计算出损失梯度后,需要优化器进行损失更新。通过以下方式引入:
optim = torch.optim.SGD(test_nn.parameters(), lr=0.01)
optim.zero_grad()
optim.step()
在整个训练流程结束后,需要保存模型,pytroch提供以下两种保存模型的方式。
import torch
#方式1, 保存模型结构和参数
torch.save(net,"XXX.pth")
#方式2,保存模型参数,用字典的方式保存
torch.save(net.state.dict(), "xxx.pth")
加载模型也有两种方式,与保存对应
import torch
#方式1
model = torch.load("xxx.pth")
#方式2
model = net()
model.load_state(torch.load("xxx.pth"))
目录结构如下:
CIFAR10
|
|---CIF_module.py
|
|---CIFAR10.py
|
|---test.py
该文件实现了模型类,给另外两个文件调用,代码如下:
import torch.nn as nn
import torch
class net(nn.Module):
def __init__(self) -> None:
super().__init__()
self.model = nn.Sequential(
nn.Conv2d(3, 32, 5, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(32, 32, 5, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(32, 64, 5, padding=2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(1024,64),
nn.Linear(64,10)
)
def forward(self, input):
input = self.model(input)
return input
if __name__ == '__main__':
#验证下模型输入张量和输出张量是否正常
net = net()
input = torch.ones((64,3,32,32))
print(input.shape)
output = net(input)
print(output.shape)
if __name__ == '__main__':
定义该语句后,可以通过python CIF_module.py
的方式调用,测试模型的输入输出的张量是否正常该文件实现了具体的网络加载训练。具体实现如下:
import torchvision
import torch
import torch.utils.data as Data
from CIF_module import *
from torch.utils.tensorboard import SummaryWriter
#可视化
writer = SummaryWriter("./log")
#加载数据集
train_set = torchvision.datasets.CIFAR10(root="./train_set", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_set = torchvision.datasets.CIFAR10(root="./test_set", train=False, transform=torchvision.transforms.ToTensor(), download=True)
test_data_size = len(test_set)
#加载测试集
train_loader = Data.DataLoader(train_set, batch_size=64)
test_loader = Data.DataLoader(test_set, batch_size=64)
#初始化网络
net = net()
if torch.cuda.is_available():
net = net.cuda()
#初始化优化器
lr = 0.003
optim = torch.optim.SGD(net.parameters(), lr)
#初始化损失函数
cross_loss = nn.CrossEntropyLoss()
if torch.cuda.is_available():
cross_loss = cross_loss.cuda()
#指定训练代数
total_epoch = 100
total_train_step = 0
total_test_step = 0
#开始迭代
print("---------开始训练----------")
for epoch in range(total_epoch):
#进入训练模式
net.train()
for data in train_loader:
img, target = data
if torch.cuda.is_available():
img = img.cuda()
target = target.cuda()
output = net(img)
#计算损失
loss = cross_loss(output, target)
#total_train_loss = total_train_loss + loss
#优化器梯度清0
optim.zero_grad()
#计算损失梯度
loss.backward()
#梯度下降
optim.step()
total_train_step=total_train_step+1
if total_train_step % 200 == 0:
print("训练次数:{},损失:{}".format(total_train_step, loss.item()))
writer.add_scalar("train_loss", loss, total_train_step)
#进入测试模式
net.eval()
total_test_loss = 0
total_test_accuracy = 0
with torch.no_grad():
for data in test_loader:
img,target = data
if torch.cuda.is_available():
img = img.cuda()
target = target.cuda()
output = net(img)
#计算损失
loss = cross_loss(output, target)
total_test_loss = total_test_loss + loss
#计算正确率
accuracy = (output.argmax(1) == target).sum()
total_test_accuracy = accuracy.item() + total_test_accuracy
print("第{}次测试的总损失:{}".format(epoch+1, total_test_loss))
print("准确率:{}".format(total_test_accuracy/test_data_size))
writer.add_scalar("test_loss", loss, total_test_step)
writer.add_scalar("accuracy", total_test_accuracy/test_data_size, total_test_step)
total_test_step = total_test_step + 1
#保存模型
torch.save(net,"./weights/CIFAR_epoch{}.pth".format(epoch))
writer.close()
该文件实现了如何测试自己的图片。
from PIL import Image
import torch
import torchvision
from CIF_module import *
classes = ["airplane","automobile","bird","cat","deer","dog","frog","horse","ship","truck"]
img_path = "./imgs/dog.png"
img_PIL = Image.open(img_path)
img_PIL = img_PIL.convert('RGB')
trans = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)), torchvision.transforms.ToTensor()])
img = trans(img_PIL)
img = torch.reshape(img,(1,3,32,32))
img = img.cuda()
print(img.shape)
net = torch.load("./weights/CIFAR_epoch99.pth")
print(net)
#进入测试模式
net.eval()
with torch.no_grad():
result = net(img)
print("结果是:{}".format(classes[result.argmax(1).item()]))