本栏目为本人自学B站各位好心的博主所录视频过程中记录下来的笔记,出处基本来自于B站视频博主以及csdn中各位大佬的解释,我只起到了转载的作用。因来源过于复杂,因此无法标注来源。
目录
1.本文环境说明
- Pytorch版本说明
# CUDA 10.2
conda install pytorch==1.10.0 torchvision==0.11.0 torchaudio==0.10.0 cudatoolkit=10.2 -c pytorch
通过Pycharm将Anaconda中虚拟环境结合一起开发,同时利用Jupyter notebook工具。
通过以下命令可以在Anaconda虚拟环境中下载Jupyter notebook:
conda install nb_conda
小tips:
Python学习中两大查看package内部结构的法宝
- dir()查看包内部有多少分隔空间
- help()查看某函数说明书
2.Pytorch数据的加载
自定义数据类MyData,继承父类(Dataset),必须至少实现两个魔术方法:getitem和len
from torch.utils.data import Dataset
from PIL import Image
import os
class MyData(Dataset):
def __init__(self,root_dir,label_dir):
self.root_dir = root_dir
self.label_dir = label_dir
self.path = os.path.join(root_dir,label_dir)
self.img_path_list = os.listdir(self.path)
def __getitem__(self, idx):
img_name = self.img_path_list[idx]
img_item_path = os.path.join(self.root_dir,self.label_dir,img_name)
img = Image.open(img_item_path)
label = self.label_dir
return img,label
def __len__(self):
return len(self.img_path_list)
3.tensorboard的使用
- 函数图像的加载
- 导入相关包
from torch.utils.tensorboard import SummaryWriter
- 实例化对象
writer = SummaryWriter("Logs")
参数说明:
实例化时填入的参数为writer对象输出结果的目录所在位置,由程序员指定
- 添加图表标题和函数表达式和x轴变量
for i in range(100):
writer.add_scalar("y=x",i,i)
常用参数
tag 图标题
scalar_value 需要保存的数值,对应于坐标轴的纵轴
global_step 对应于坐标轴的横轴
- 打开所绘制的函数图像
# 在命令行中输入以下命令
# logdir是指的writer对象所填的结果输出目录
# port是指打开图像的指定端口号,一般默认为6006
tensorboard --logdir=Logs --port=6007
- 图片的加载
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
import numpy as np
writer = SummaryWriter("Logs")
image_path = "dataset/train/ants/0013035.jpg"
img_PIL = Image.open(image_path)
img_array = np.array(img_PIL)
writer.add_image("train",img_array,1,dataformats="HWC")
writer.close()
注:add_image中可接受Torch.tensor和numpy.array等图片数据格式,但不支持PIL格式的,因此要进行数据格式转换。此外,转换为numpy.array格式时,还需要对HWC进行一次调整,调整为CHW
4.transforms的使用
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from PIL import Image
img_path = "dataset/train/ants/0013035.jpg"
img_PTL = Image.open(img_path)
writer = SummaryWriter("Logs")
# ToTensor类的使用,将数据类型转化为tensor
tensor_transform = transforms.ToTensor()
img_tensor = tensor_transform(img_PTL)
writer.add_image("Tensor_img",img_tensor)
# Normalize类的使用,对图片进行标准化,第一个参数为mean,第二个参数为std
normalize_transform = transforms.Normalize([0.5,0.5,0.5],[1,1,1])
img_normalize = normalize_transform(img_tensor)
writer.add_image("Normalize_img",img_normalize)
# Resize类的使用,对图片不按照比例进行放缩,参数为一个元组,分别表示长和宽
resize_transform = transforms.Resize((512,512))
img_resize = resize_transform(img_tensor)
writer.add_image("Resize_img",img_resize)
# Compose类的使用,对图片进行一系列操作,如转换数据类型,归一化,放缩等等
compose_transform = transforms.Compose([
transforms.Resize((256, 256)), # 调整图像大小为 256x256
transforms.RandomCrop(224), # 随机裁剪为 224x224
transforms.RandomHorizontalFlip(),# 随机水平翻转
transforms.ToTensor(), # 转换为张量
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 标准化
])
img_compose = compose_transform(img_PTL)
writer.add_image("Compose_img",img_compose)
writer.close()
5.卷积层
from torch.utils.tensorboard import SummaryWriter
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch import nn
import torchvision
import torch
data = torchvision.datasets.CIFAR10(root="../dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(data,batch_size=64)
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.conv1 = Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)
def forward(self,x):
x = self.conv1(x)
return x
mymodel = MyModel()
writer = SummaryWriter("../Logs")
step = 0
for data in dataloader:
imgs_input,target = data
writer.add_images("input images",imgs_input,global_step=step)
imgs_output = mymodel.forward(imgs_input)
imgs_output = torch.reshape(imgs_output,[-1,3,30,30])
writer.add_images("output images",imgs_output,global_step=step)
step = step + 1
writer.close()
6.池化层(最大池化)
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from torch import nn
import torchvision
dataset = torchvision.datasets.CIFAR10(root="../dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=4)
class PoolModel(nn.Module):
def __init__(self):
super(PoolModel, self).__init__()
self.MaxPool = MaxPool2d(kernel_size=4)
def forward(self,input):
output = self.MaxPool(input)
return output
poolmodel = PoolModel()
writer = SummaryWriter("../Logs")
step = 0
for data in dataloader:
imgs_input,targets = data
writer.add_images("input images",imgs_input,global_step=step)
imgs_output = poolmodel.forward(imgs_input)
writer.add_images("output images",imgs_output,global_step=step)
step = step + 1
writer.close()
7.非线性激活层(Sigmoid)
import torchvision
from torch import nn
from torch.nn import Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10(root="../dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=36)
class SigmoidModel(nn.Module):
def __init__(self):
super(SigmoidModel, self).__init__()
self.sigmoid1 = Sigmoid()
def forward(self,input):
output = self.sigmoid1(input)
return output
sigmoidmodel = SigmoidModel()
writer = SummaryWriter("../Logs")
step = 0
for data in dataloader:
imgs_input,targets = data
writer.add_images("input images",imgs_input,step)
imgs_output = sigmoidmodel(imgs_input)
writer.add_images("output images",imgs_output,step)
step = step + 1
writer.close()
8.Sequential容器
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter
class Mymodel(nn.Module):
def __init__(self):
super(Mymodel, self).__init__()
# self.conv1 = Conv2d(in_channels=3,out_channels=32,kernel_size=5,stride=1,padding=2)
# self.maxpool1 = MaxPool2d(kernel_size=2)
# self.conv2 = Conv2d(in_channels=32,out_channels=32,kernel_size=5,stride=1,padding=2)
# self.maxpool2 = MaxPool2d(kernel_size=2)
# self.conv3 = Conv2d(in_channels=32,out_channels=64,kernel_size=5,stride=1,padding=2)
# self.maxpool3 = MaxPool2d(kernel_size=2)
# self.flatten = Flatten()
# self.linear1 = Linear(1024,64)
# self.linear2 = Linear(64,10)
self.sequential1 = Sequential(
Conv2d(3,32,5,1,2),
MaxPool2d(2),
Conv2d(32,32,5,1,2),
MaxPool2d(2),
Conv2d(32,64,5,1,2),
MaxPool2d(2),
Flatten(),
Linear(1024,64),
Linear(64,10)
)
def forward(self,x):
# x = self.conv1(x)
# x = self.maxpool1(x)
# x = self.conv2(x)
# x = self.maxpool2(x)
# x = self.conv3(x)
# x = self.maxpool3(x)
# x = self.flatten(x)
# x = self.linear1(x)
# x = self.linear2(x)
x = self.sequential1(x)
return x
mymodel = Mymodel()
writer = SummaryWriter("../Logs")
input = torch.ones(64,3,32,32)
writer.add_graph(mymodel,input)
writer.close()
9.损失函数
9.1 L1和MSE
import torch
from torch.nn import L1Loss,MSELoss
input = torch.tensor([1,7,9],dtype=torch.float32)
target = torch.tensor([3,8,1],dtype=torch.float32)
input = torch.reshape(input,[1,1,1,3])
target = torch.reshape(target,[1,1,1,3])
loss_L1 = L1Loss(reduction="sum")
result_L1 = loss_L1(input,target)
print("L1_loss为:",result_L1)
loss_MSE = MSELoss()
result_MSE = loss_MSE(input,target)
print("MSE_loss为:",result_MSE)
9.2 CrossEntropyLoss
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential, CrossEntropyLoss
from torch.utils.data import DataLoader
dataset = torchvision.datasets.CIFAR10(root="../dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=36)
class Mymodel(nn.Module):
def __init__(self):
super(Mymodel, self).__init__()
self.sequential1 = Sequential(
Conv2d(3,32,5,1,2),
MaxPool2d(2),
Conv2d(32,32,5,1,2),
MaxPool2d(2),
Conv2d(32,64,5,1,2),
MaxPool2d(2),
Flatten(),
Linear(1024,64),
Linear(64,10)
)
def forward(self,x):
x = self.sequential1(x)
return x
mymodel = Mymodel()
loss = CrossEntropyLoss()
for data in dataloader:
imgs_input,targets = data
imgs_output = mymodel(imgs_input)
result = loss(imgs_output,targets)
print(result)
10.优化器
随机梯度下降(SGD)
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential, CrossEntropyLoss
from torch.optim import SGD
from torch.utils.data import DataLoader
dataset = torchvision.datasets.CIFAR10(root="../dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=36)
class Mymodel(nn.Module):
def __init__(self):
super(Mymodel, self).__init__()
self.sequential1 = Sequential(
Conv2d(3,32,5,1,2),
MaxPool2d(2),
Conv2d(32,32,5,1,2),
MaxPool2d(2),
Conv2d(32,64,5,1,2),
MaxPool2d(2),
Flatten(),
Linear(1024,64),
Linear(64,10)
)
def forward(self,x):
x = self.sequential1(x)
return x
mymodel = Mymodel()
loss = CrossEntropyLoss()
optimizer = SGD(mymodel.parameters(),lr=0.01)
for epoch in range(20):
running_loss = 0.0
for data in dataloader:
imgs_input,targets = data
imgs_output = mymodel(imgs_input)
result = loss(imgs_output,targets)
optimizer.zero_grad()
result.backward()
optimizer.step()
running_loss = result + running_loss
print("第{}轮的损失为: {}".format(epoch,running_loss))
11.模型的添加与修改
import torchvision
from torch import nn
vgg16_false = torchvision.models.vgg16(pretrained=False)
vgg16_true = torchvision.models.vgg16(pretrained=True)
print(vgg16_true)
print(vgg16_false)
# 添加模型
vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
print(vgg16_true)
# 修改模型
vgg16_false.classifier[6] = nn.Linear(4096, 10)
print(vgg16_false)
12.模型的保存与加载
12.1 模型的保存
import torch
import torchvision
from torch import nn
vgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式1,模型结构+模型参数
torch.save(vgg16, "vgg16_method1.pth")
# 保存方式2,模型参数(官方推荐)
torch.save(vgg16.state_dict(), "vgg16_method2.pth")
# 陷阱
class Tudui(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=3)
def forward(self, x):
x = self.conv1(x)
return x
tudui = Tudui()
torch.save(tudui, "tudui_method1.pth")
12.2 模型的加载
import torch
import torchvision
from torch import nn
# 方式1,加载模型结构+模型参数
model1 = torch.load("vgg16_method1.pth")
print(model1)
# 方式2,加载模型参数
model2 = torchvision.models.vgg16(pretrained=False)
model2.load_state_dict(torch.load("vgg16_method2.pth"))
print(model2)
# 陷阱
class Tudui(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=3)
def forward(self, x):
x = self.conv1(x)
return x
model3 = torch.load('tudui_method1.pth')
print(model3)
13.完整的模型训练过程
13.1 普通版
import torch
import torchvision
from torch.utils.tensorboard import SummaryWriter
from torch import nn
from torch.nn import Sequential ,CrossEntropyLoss
from torch.utils.data import DataLoader
# 1.准备数据集
train_dataset = torchvision.datasets.CIFAR10(root="../dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_dataset = torchvision.datasets.CIFAR10(root="../dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
print("训练数据集的长度为:",len(train_dataset))
print("测试数据集的长度为:",len(test_dataset))
# 2.加载数据集
train_dataloader = DataLoader(train_dataset,batch_size=64)
test_dataloader = DataLoader(test_dataset,batch_size=64)
# 3.创建网络模型
class CIFAR10_Model(nn.Module):
def __init__(self):
super(CIFAR10_Model, self).__init__()
self.model = Sequential(
nn.Conv2d(3,32,5,1,2),
nn.MaxPool2d(2),
nn.Conv2d(32,32,5,1,2),
nn.MaxPool2d(2),
nn.Conv2d(32,64,5,1,2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(1024,64),
nn.Linear(64,10)
)
def forward(self,x):
x = self.model(x)
return x
cifar10_model = CIFAR10_Model()
# 4.损失函数
loss = CrossEntropyLoss()
# 5.优化器
optimizer = torch.optim.SGD(cifar10_model.parameters(),lr=1e-2)
# 6.设置训练参数及可视化
## 训练次数(一个batch算作一次)
total_train_step = 0
## 测试次数(一个batch算作一次)
total_test_step = 0
## 训练轮数
epoch = 30
## tensorboard可视化
writer = SummaryWriter("CIFAR10_Model_logs")
# 7.开始训练
for i in range(epoch):
print("----------------第{}轮训练开始---------------".format(i))
# 训练步骤开始
cifar10_model.train()
for data in train_dataloader:
imgs_input,targets = data
imgs_output = cifar10_model(imgs_input)
loss_train = loss(imgs_output,targets)
# 优化器开始优化
optimizer.zero_grad()
loss_train.backward()
optimizer.step()
total_train_step = total_train_step + 1
if total_train_step % 100 == 0:
print("第{}次训练的Loss为: {}".format(total_train_step, loss_train))
writer.add_scalar("loss_train",loss_train,total_train_step)
# 测试步骤开始
cifar10_model.eval()
total_test_loss = 0
total_test_accurate = 0
with torch.no_grad():
for data in test_dataloader:
imgs_input,targets = data
imgs_output = cifar10_model(imgs_input)
loss_test = loss(imgs_output,targets)
total_test_loss = total_test_loss + loss_test
right_nums = (imgs_output.argmax(1) == targets).sum()
total_test_accurate = total_test_accurate + right_nums
print("第{}轮训练后,在测试集上的损失loss为:{}".format(i,total_test_loss))
print("第{}轮训练后,在测试集上的正确率accuracy为:{}%".format(i, (total_test_accurate/len(test_dataset))*100))
writer.add_scalar("loss_test",total_test_loss,total_test_step)
writer.add_scalar("accuracy_test",(total_test_accurate/len(test_dataset))*100,total_test_step)
total_test_step = total_test_step + 1
torch.save(cifar10_model,"cifar10_model_{}.pth".format(i))
print("第{}轮训练的模型已保存".format(i))
writer.close()
13.2 利用GPU加速版
import torch
import torchvision
from torch.utils.tensorboard import SummaryWriter
from torch import nn
from torch.nn import Sequential ,CrossEntropyLoss
from torch.utils.data import DataLoader
import time
# 0.设置训练的设备
device = torch.device("cuda")
# 1.准备数据集
train_dataset = torchvision.datasets.CIFAR10(root="../dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_dataset = torchvision.datasets.CIFAR10(root="../dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
print("训练数据集的长度为:",len(train_dataset))
print("测试数据集的长度为:",len(test_dataset))
# 2.加载数据集
train_dataloader = DataLoader(train_dataset,batch_size=64)
test_dataloader = DataLoader(test_dataset,batch_size=64)
# 3.创建网络模型
class CIFAR10_Model(nn.Module):
def __init__(self):
super(CIFAR10_Model, self).__init__()
self.model = Sequential(
nn.Conv2d(3,32,5,1,2),
nn.MaxPool2d(2),
nn.Conv2d(32,32,5,1,2),
nn.MaxPool2d(2),
nn.Conv2d(32,64,5,1,2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(1024,64),
nn.Linear(64,10)
)
def forward(self,x):
x = self.model(x)
return x
cifar10_model = CIFAR10_Model()
cifar10_model = cifar10_model.to(device)
# 4.损失函数
loss = CrossEntropyLoss()
loss = loss.to(device)
# 5.优化器
optimizer = torch.optim.SGD(cifar10_model.parameters(),lr=1e-2)
# 6.设置训练参数及可视化
## 训练次数(一个batch算作一次)
total_train_step = 0
## 测试次数(一个batch算作一次)
total_test_step = 0
## 训练轮数
epoch = 30
## tensorboard可视化
writer = SummaryWriter("../CIFAR10_Model_logs")
## 计时器
start_time = time.time()
# 7.开始训练
for i in range(epoch):
print("----------------第{}轮训练开始---------------".format(i))
# 训练步骤开始
cifar10_model.train()
for data in train_dataloader:
imgs_input,targets = data
imgs_input = imgs_input.to(device)
targets = targets.to(device)
imgs_output = cifar10_model(imgs_input)
loss_train = loss(imgs_output,targets)
# 优化器开始优化
optimizer.zero_grad()
loss_train.backward()
optimizer.step()
total_train_step = total_train_step + 1
if total_train_step % 100 == 0:
end_time = time.time()
print("第{}次训练的Loss为: {}".format(total_train_step, loss_train))
print("第{}次训练的费时为: {}".format(total_train_step, end_time-start_time))
writer.add_scalar("loss_train",loss_train,total_train_step)
# 测试步骤开始
cifar10_model.eval()
total_test_loss = 0
total_test_accurate = 0
with torch.no_grad():
for data in test_dataloader:
imgs_input,targets = data
imgs_input = imgs_input.to(device)
targets = targets.to(device)
imgs_output = cifar10_model(imgs_input)
loss_test = loss(imgs_output,targets)
total_test_loss = total_test_loss + loss_test
right_nums = (imgs_output.argmax(1) == targets).sum()
total_test_accurate = total_test_accurate + right_nums
print("第{}轮训练后,在测试集上的损失loss为:{}".format(i,total_test_loss))
print("第{}轮训练后,在测试集上的正确率accuracy为:{}%".format(i, (total_test_accurate/len(test_dataset))*100))
writer.add_scalar("loss_test",total_test_loss,total_test_step)
writer.add_scalar("accuracy_test",(total_test_accurate/len(test_dataset))*100,total_test_step)
total_test_step = total_test_step + 1
torch.save(cifar10_model,"cifar10_model_{}.pth".format(i))
print("第{}轮训练的模型已保存".format(i))
writer.close()
14.模型验证
from PIL import Image
from torch import nn
from torch.nn import Sequential
import torchvision
import torch
# 0.指定设备
device = torch.device("cuda")
# 1.准备数据
img_path = "../images/airplane.jpg"
img = Image.open(img_path)
img = img.convert("RGB")
## 设置转换器
transform = torchvision.transforms.Compose([
torchvision.transforms.Resize((32,32)),
torchvision.transforms.ToTensor()
])
img = transform(img)
## 设置batch
img = torch.reshape(img,(1,3,32,32))
## 设置为cuda模式
img = img.to(device)
# 2.加载网络模型
class CIFAR10_Model(nn.Module):
def __init__(self):
super(CIFAR10_Model, self).__init__()
self.model = Sequential(
nn.Conv2d(3,32,5,1,2),
nn.MaxPool2d(2),
nn.Conv2d(32,32,5,1,2),
nn.MaxPool2d(2),
nn.Conv2d(32,64,5,1,2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(1024,64),
nn.Linear(64,10)
)
def forward(self,x):
x = self.model(x)
return x
cifar10_model = torch.load("../train_models/cifar10_model_26.pth",map_location=device)
# 3.验证模型
cifar10_model.eval()
with torch.no_grad():
output_img = cifar10_model(img)
target_index = output_img.argmax(1)
print(output_img)
print(target_index)