这里写目录标题
打开tensorboard
tensorboard --logdir="D:\6.PyCharm\1项目代码\test\logs_池化层"
前置API:
# 1.root="./dataset"当前文件的相对位置 , 2.train=True是为训练集(不是测试集), 3.transform=将图片使用该方法转换, 4.download=True下载到root路径中
dataset = torchvision.datasets.CIFAR10(root='./dataset',train=False,transform=transform,download=True) # 下载测试集
# 1.dataset=test_set:数据集, 2.batch_size=4:一次取四张图片, 3.shuffle=False(默认):不打乱顺序, 4.num_workers=0:进程数, 5.drop_last=False(默认):保留最后不能整除
dataloader = DataLoader(dataset=dataset, batch_size=64)
# 标签要不同、step要不同
writer.add_images("input", imgs, step)
writer.add_images("output", output, step)
1.卷积层:提取特征
卷积层API:
# 输入的通道数、输出的通道数、卷积核大小、步长(默认1)、填充(默认0)
self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)
# 输出通道数out_channels = 卷积核的个数
#
import torchvision
import torch
from torch.utils.data import DataLoader
from torch import nn
from torch.nn import Conv2d
from torch.utils.tensorboard import SummaryWriter
# torchvision->transforms->[Compose...]
# torchvision->datasets->CIFAR10
# torch.utils.data-> DataLoader
# torch.nn->Module
# torch.utils.tensorboard->SummaryWriter
'''
# 图像格式预处理
'''
transform = torchvision.transforms.Compose([
torchvision.transforms.ToTensor()
])
'''
# 读入数据集
'''
# 1.root="./dataset"当前文件的相对位置 , 2.train=True是为训练集(不是测试集), 3.transform=将图片使用该方法转换, 4.download=True下载到root路径中
dataset = torchvision.datasets.CIFAR10(root='./dataset',train=False,transform=transform,download=True) # 下载测试集
'''
# 小批量的数据读入
'''
# 1.dataset=test_set:数据集, 2.batch_size=4:一次取四张图片, 3.shuffle=False(默认):不打乱顺序, 4.num_workers=0:进程数, 5.drop_last=False(默认):保留最后不能整除
dataloader = DataLoader(dataset=dataset, batch_size=64)
'''
# 建立模型
'''
class MyModule(nn.Module):
def __init__(self):
super(MyModule, 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
mymodule = MyModule()
# print(mymodule)
writer = SummaryWriter("./logs_卷积层")
# data是64张图片
step = 0
for data in dataloader:
# imgs = 64张图片,targets =64张图片的正确标签
imgs, targets = data
output = mymodule(imgs)
writer.add_images("input", imgs, step)
# 图片展示需要三个通道
output = torch.reshape(output, (-1, 3, 30, 30))
writer.add_images("output", output, step)
step = step + 1
# print(imgs.shape)
# print(output.shape)
writer.close()
2.池化层:减少特征
池化不需要reshape了,因为通道数没有改变(MaxPool2d没有参数涉及到通道数)
池化层API
# 1.kernel_size=3:池化核大小 2.ceil_mode=true:向上取整, 3.步长stride=kernel_size(默认)
self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)
import torch
import torchvision.datasets
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
# 图片预处理
from torch.utils.tensorboard import SummaryWriter
transform = torchvision.transforms.Compose([
torchvision.transforms.ToTensor()
])
# 加载数据集
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=transform, download=True)
# 小批量读入
dataloader = DataLoader(dataset=dataset,batch_size=64)
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
# 1.kernel_size=3:池化核大小 2.ceil_mode=true:向上取整, 3.stride=kernel_size(默认)
self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)
def forward(self, input):
output = self.maxpool1(input)
return output
mymodule = MyModule()
writer = SummaryWriter("./logs_池化层")
step = 0
for data in dataloader:
imgs, targets = data
output = mymodule(imgs)
writer.add_images("input", imgs, step)
writer.add_images("output", output, step)
step = step + 1
writer.close()
3.非线性激活
3.1ReLU函数
ReLU函数API:
torch.nn.ReLU(inplace=False)
具体函数:ReLU(x) =max(0,x)
图像:
3.1.1处理tensor
import torch
from torch import nn
from torch.nn import ReLU
input = torch.tensor([[1, -0.5],
[-1, 3]])
input = torch.reshape(input, (-1, 1, 2, 2))
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.relu1 = ReLU()
def forward(self, input):
output = self.relu1(input)
return output
mymodule = MyModule()
output = mymodule(input)
print(output)
3.1.2处理图片
将图片过ReLU函数
import torch
import torchvision.datasets
from torch import nn
from torch.nn import ReLU,Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
transform = torchvision.transforms.Compose([
torchvision.transforms.ToTensor()
])
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=transform, download=True)
dataloader = DataLoader(dataset=dataset, batch_size=64)
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.relu1 = ReLU()
self.sigmoid1 = Sigmoid()
def forward(self, input):
output = self.relu1(input)
return output
mymodule = MyModule()
writer = SummaryWriter("./logs_非线性激活ReLU")
step = 0
for data in dataloader:
imgs, targets = data
writer.add_images("input", imgs, step)
output = mymodule(imgs)
writer.add_images("output", output, step)
step += 1
writer.close()
几乎没有差别
3.2Sigmoid函数
API
torch.nn.Sigmoid(*args, **kwargs)
3.2.1处理图片
import torch
import torchvision.datasets
from torch import nn
from torch.nn import ReLU,Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
transform = torchvision.transforms.Compose([
torchvision.transforms.ToTensor()
])
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=transform, download=True)
dataloader = DataLoader(dataset=dataset, batch_size=64)
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.relu1 = ReLU()
self.sigmoid1 = Sigmoid()
def forward(self, input):
output = self.sigmoid1(input)
return output
mymodule = MyModule()
writer = SummaryWriter("./logs_非线性激活Sigmoid")
step = 0
for data in dataloader:
imgs, targets = data
writer.add_images("input", imgs, step)
output = mymodule(imgs)
writer.add_images("output", output, step)
step += 1
writer.close()
4.线性层
API:
in_features (int) – 每个输入样本的大小
out_features (int) – 每个输出样本的大小
bias (bool) – 默认True
torch.nn.Linear(in_features, out_features, bias=True, device=None, dtype=None)
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.nn import Linear
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64)
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.linear1 = Linear(196608, 10)
def forward(self, input):
output = self.linear1(input)
return output
mymodule = MyModule()
for data in dataloader:
imgs, targets = data
print(imgs.shape)
# print(64*3*32*32)
# input = torch.reshape(imgs, (1, 1, 1, -1))
input = torch.flatten(imgs)
print(input.shape)
output = mymodule(input)
print(output.shape)
5.小实战+Sequential使用
如果前后尺寸不变的话,那么padding=(f-1)/2,f是卷积核的尺寸,也就是5,所以padding=(5-1)/2=2
import torch
from torch import nn
from torch.nn import Conv2d,MaxPool2d,Flatten,Linear,Sequential
from torch.utils.tensorboard import SummaryWriter
class My(nn.Module):
def __init__(self):
super(My, self).__init__()
# 繁琐版本
'''
# 公式推算出来的s and p (卷积核中心对准最边缘的那个==》5/2=2)
self.conv1 = Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2)
# 公式推算
self.maxpool1 = MaxPool2d(kernel_size=2, stride=2, padding=0)
# 公式推算
self.conv2 = Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2)
# 公式推算
self.maxpool2 = MaxPool2d(kernel_size=2, stride=2, padding=0)
self.conv3 = Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2)
self.maxpool3 = MaxPool2d(kernel_size=2, stride=2, padding=0)
self.flatten = Flatten()
self.linear1 = Linear(1024, 64)
self.linear2 = Linear(64, 10)
'''
# 简化版本
self.model1 = Sequential(
Conv2d(3, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=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.model1(x)
return x
my = My()
print(my)
# 模型是否错误、验证
input = torch.ones((64, 3, 32, 32))
output = my(input)
print(output.shape)
writer = SummaryWriter("./logs_Sequential")
writer.add_graph(my, input)
writer.close()
6.损失函数
6.1L1Loss
6.2MSELoss
6.3CrossEntropyLoss
egg:
import torch
from torch.nn import L1Loss, MSELoss, CrossEntropyLoss
inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
targets = torch.tensor([1, 2, 5], dtype=torch.float32)
inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))
# egg:L1Loss(reduction='sum') 下边三个损失函数都可以使用
# reduction='sum':差值的绝对值相加
# reduction='mean'(默认):差值的绝对值相加的平均值
loss = L1Loss()
loss_mse = MSELoss()
ans1 = loss(inputs, targets)
ans2 = loss_mse(inputs, targets)
print(ans1)
print(ans2)
# 预测概率
x = torch.tensor([0.1, 0.2, 0.3])
# 真实值
y = torch.tensor([1])
# 必须有3=》分类的类数
x = torch.reshape(x, (1, 3))
loss_cross = CrossEntropyLoss()
ans3 = loss_cross(x, y)
print(ans3)
7.反向传播
就一句话:loss.backward()
import torch
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d,MaxPool2d,Flatten,Linear,Sequential,CrossEntropyLoss
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset=dataset, batch_size=64)
class My(nn.Module):
def __init__(self):
super(My, self).__init__()
# 简化版本
self.model1 = Sequential(
Conv2d(3, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self, x):
# 简化版本
x = self.model1(x)
return x
my = My()
# 参数:一张图片的[各个分类的概率、真实分类]
# 比如三分类,参数就是,预测概率[0.1,0.2,0.3] 真实分类[1]
loss_cross = CrossEntropyLoss()
for data in dataloader:
imgs, targets = data
outputs = my(imgs)
# print(outputs) # 一张图片预测的分类的概率[10个概率值]
# print(targets) # 真实分类
loss = loss_cross(outputs, targets)
# 损失函数的反向传播
loss.backward()
print("每bacth图片上的损失值:", loss)
8.优化器
引入
optim = torch.optim.SGD(my.parameters(), lr=0.01)
三步:1.清零 2.反向传播 3.调优
loss = loss_cross(outputs, targets)
optim.zero_grad() #参数置0
loss.backward() #方向传播、求梯度
optim.step() #参数调优
import torch
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d,MaxPool2d,Flatten,Linear,Sequential,CrossEntropyLoss
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset=dataset, batch_size=64)
class My(nn.Module):
def __init__(self):
super(My, self).__init__()
# 简化版本
self.model1 = Sequential(
Conv2d(3, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self, x):
# 简化版本
x = self.model1(x)
return x
my = My()
loss_cross = CrossEntropyLoss()
optim = torch.optim.SGD(my.parameters(), lr=0.01)
for k in range(20):
sum_loss = 0
for data in dataloader:
imgs, targets = data
outputs = my(imgs)
loss = loss_cross(outputs, targets)
optim.zero_grad() #参数置0
loss.backward() #方向传播、求梯度
optim.step() #参数调优
sum_loss += loss
print("每一轮的损失值:", sum_loss)
9.加载现有模型、并且修改
import os
import torchvision
from torchvision import models
from torchvision.models import vgg16
from torch import nn
# 修改下载路径
os.environ['TORCH_HOME']='D:\\6.PyCharm\\1项目代码\\test\models'
# 不自带参数
vgg16_false = vgg16(weights=None)
# 自带参数
vgg16_true = vgg16(weights=models.VGG16_Weights.DEFAULT)
print(vgg16_true)
# print(vgg16_false)
vgg16_true.add_module('add_linear1', nn.Linear(1000, 10))
print(vgg16_true)
vgg16_true.classifier.add_module('add_linear2', nn.Linear(1000, 10))
print(vgg16_true)
vgg16_true.classifier[6] = nn.Linear(4096, 10)
print(vgg16_true)
添加
vgg16_true.add_module('add_linear', nn.Linear(1000, 10))
vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
修改
vgg16_true.classifier[6] = nn.Linear(4096, 10)
原来:
修改后:
10.网络模型的保存和读入
10.1网上加载的模型
获取模型:
os.environ['TORCH_HOME']='D:\\6.PyCharm\\1项目代码\\study_pytorch\models'
vgg16 = torchvision.models.vgg16(weights=torchvision.models.VGG16_Weights.DEFAULT)
保存模型:
# 保存模型法1:保存参数,保存结构
torch.save(vgg16, "./vgg16_1.pth")
# 保存模型法2:保存参数,不保存结构
torch.save(vgg16.state_dict(), "./vgg16_2.pth")
加载模型:
# 加载法1:
# weights_only不知道社么意思
load_model1 = torch.load('./vgg16_1.pth', weights_only=False)
print(load_model1)
# 加载法2:
# 1.输出是参数字典
load_model2 = torch.load('./vgg16_2.pth', weights_only=False)
print(load_model2)
# 2.输出的结构
vgg16 = torchvision.models.vgg16(weights=torchvision.models.VGG16_Weights.DEFAULT) # 获取模型
vgg16.load_state_dict(torch.load('./vgg16_2.pth', weights_only=False)) # 加载参数->放入模型
print(vgg16)
10.2加载自定义模型
保存模型:
文件1.py:
# 保存模型法1:自定义模型
class MyModule(nn.Module):
def __init__(self):
super(MyModule, 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
mymodule = MyModule()
torch.save(mymodule, "./mymodule.pth")
文件2.py:
# 加载法1:自定义模型
mymodule = torch.load('./mymodule.pth', weights_only=False)
print(mymodule)
以上代码回会出错。
解决办法:
1.加入class MyModule(nn.Module):XXXX
自己模型的代码。
# 保存模型法1:自定义模型
class MyModule(nn.Module):
def __init__(self):
super(MyModule, 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
# 加载法1:自定义模型
mymodule = torch.load('./mymodule.pth', weights_only=False)
print(mymodule)
2.from model import *
直接导入,注意model是.py模型文件