赞
踩
目录
pytorch官网:torchvision — Torchvision master documentation (pytorch.org)
1、conda create -n pycyy python=3.7 -c 镜像地址
以下是一些常见的conda镜像地址:
- 清华大学:
https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
- 阿里云:
https://mirrors.aliyun.com/anaconda/pkgs/main/
- 北京外国语大学:
https://mirrors.bfsu.edu.cn/anaconda/pkgs/main/
2、conda activate pycyy
3、在pytorch官网复制上述python版本对应的pytorch配置代码,如:conda install pytorch torchvision torchaudio cpuonly -c pytorch
[i]
1、利用PyCharm打开项目:File->Open
2、配置相应的虚拟环境:File->Setting->Project->Python解释器。然后选择对应的虚拟环境
3、直接运行代码,右键->run
4、如果提示某些包没有发现,可以用
conda activate pycyy
conda install 包名
pip insatll 包名
利用搜索引擎找原因 - 包名不对、通道不对,或者其他原因
5、可选 - 最好把requirements.txt文件内容当做参考,有选择性使用
conda activate pycyy
jupyter notebook D:
[i]
Jupyter Notebook(pycyy)属性:
[i]
目标:D:\software\anaconda\Ana\python.exe D:\software\anaconda\Ana\cwp.py D:\software\anaconda\Ana\envs\pycyy D:\software\anaconda\Ana\envs\pycyy\python.exe D:\software\anaconda\Ana\envs\pycyy\Scripts\jupyter-notebook-script.py "%USERPROFILE%/"
将"%USERPROFILE%/"改为"D:\"即打开Jupyter Notebook(pycyy)直接进入D盘,不用在每次都执行jupyter notebook D:命令
提供一种方式获取数据及其label
如何获取每一个数据及其label
告诉我们总共有多少个数据
为网络提供不同的数据形式(如压缩形式)
可以看到图片的宽、高等相关属性信息
- from torch.utils.tensorboard import SummaryWriter
- writer = SummaryWriter("logs")
- # writer.add_image()
- for i in range(100):
- writer.add_scalar("y=x",i,i)
- writer.close()
tensorboard --logdir=logs --port=6007,指定端口打开tensorboard 页面
tensorboard 页面如下:
绘制了一个y=x的函数
- from PIL import Image
-
- from torchvision import transforms
- image_path = "data/train/ants_image/6743948_2b8c096dda.jpg"
- img = Image.open(image_path)
- tensor_trans = transforms.ToTensor()
- tensor_img = tensor_trans(img)
- print(tensor_img)
-
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\Transforms.py tensor([[[0.6549, 0.5451, 0.5765, ..., 0.7451, 0.7451, 0.7647], [0.4078, 0.4471, 0.5373, ..., 0.8118, 0.8431, 0.8627], [0.3529, 0.5804, 0.7490, ..., 0.6824, 0.8314, 0.8824], ..., [0.5490, 0.5412, 0.4353, ..., 0.6510, 0.6706, 0.6275], [0.8824, 0.5020, 0.8353, ..., 0.6745, 0.6706, 0.5608], [0.6235, 0.3961, 0.7765, ..., 0.7765, 0.6784, 0.6196]], [[0.6235, 0.5020, 0.5294, ..., 0.6706, 0.6353, 0.6353], [0.3529, 0.3922, 0.4824, ..., 0.7451, 0.7608, 0.7569], [0.2863, 0.5098, 0.6863, ..., 0.6196, 0.7725, 0.8157], ..., [0.4824, 0.4667, 0.3529, ..., 0.5569, 0.5843, 0.5529], [0.8314, 0.4392, 0.7608, ..., 0.5843, 0.5882, 0.4863], [0.5922, 0.3490, 0.7059, ..., 0.6902, 0.5961, 0.5490]], [[0.5412, 0.4157, 0.4353, ..., 0.6118, 0.5804, 0.5686], [0.3529, 0.3804, 0.4471, ..., 0.6431, 0.6471, 0.6392], [0.3569, 0.5569, 0.6902, ..., 0.4784, 0.6118, 0.6431], ..., [0.4039, 0.4000, 0.2863, ..., 0.5098, 0.5294, 0.4941], [0.7569, 0.3765, 0.7059, ..., 0.5216, 0.5216, 0.4196], [0.5176, 0.2863, 0.6588, ..., 0.6078, 0.5137, 0.4627]]]) Process finished with exit code 0
- import torchvision
- from torch.utils.tensorboard import SummaryWriter
-
- dataset_transform = torchvision.transforms.Compose([
- torchvision.transforms.ToTensor()
- ])
- train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, transform=dataset_transform, download=True)
- test_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, transform=dataset_transform, download=True)
- # img, target = test_set[0]
- # print(img)
- # print(target)
- # img.show()
-
- writer = SummaryWriter("p10")
- for i in range(10):
- img,target = test_set[i]
- writer.add_image("test_set", img, i)
- writer.close()
-
[i]
Neural network简称nn,nn.Module为神经网络的基本骨架的搭建
- import torch
- from torch import nn
-
- class Jzh(nn.Module):
- # 初始化
- def __int__(self):
- super(Jzh, self).__int__()
-
- # 功能函数
- def forward(self, input):
- output = input + 1
- return output
-
- jzh = Jzh()
- x = torch.tensor(1.0)
- output = jzh(x)
- print(output)
-
- import torch
-
- # 输入图像
- input = torch.tensor([[1, 2, 0, 3, 1],
- [0, 1, 2, 3, 1],
- [1, 2, 1, 0, 0],
- [5, 2, 3, 1, 1],
- [2, 1, 0, 1, 1]])
- # 卷积核
- kernel = torch.tensor([[1, 2, 1],
- [0, 1, 0],
- [2, 1, 0]])
-
- # 换一种数据的输入方式,这样打印出来的数据会有所不同
- input = torch.reshape(input, (1, 1, 5, 5))
- kernel = torch.reshape(kernel, (1, 1, 3, 3))
-
- print(input.shape)
- print(kernel.shape)
-
如下是不做torch.reshape()操作输出的数据尺寸:
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\nn_conv.py
torch.Size([5, 5])
torch.Size([3, 3])Process finished with exit code 0
如下是经过orch.reshape()操作输出的数据尺寸:
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\nn_conv.py
torch.Size([1, 1, 5, 5])
torch.Size([1, 1, 3, 3])Process finished with exit code 0
- import torch
- import torch.nn.functional as F
-
- # 输入图像
- input = torch.tensor([[1, 2, 0, 3, 1],
- [0, 1, 2, 3, 1],
- [1, 2, 1, 0, 0],
- [5, 2, 3, 1, 1],
- [2, 1, 0, 1, 1]])
- # 卷积核
- kernel = torch.tensor([[1, 2, 1],
- [0, 1, 0],
- [2, 1, 0]])
-
- # 换一种数据的输入方式,这样打印出来的数据会有所不同
- input = torch.reshape(input, (1, 1, 5, 5))
- kernel = torch.reshape(kernel, (1, 1, 3, 3))
-
- print(input.shape)
- print(kernel.shape)
-
- output = F.conv2d(input, kernel, stride=1)
- print(output)
-
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\nn_conv.py
torch.Size([1, 1, 5, 5])
torch.Size([1, 1, 3, 3])
tensor([[[[10, 12, 12],
[18, 16, 16],
[13, 9, 3]]]])Process finished with exit code 0
若再补充如下代码:
- output2 = F.conv2d(input, kernel, stride=1, padding=1)
- print(output2)
则输出为:
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\nn_conv.py
torch.Size([1, 1, 5, 5])
torch.Size([1, 1, 3, 3])
tensor([[[[10, 12, 12],
[18, 16, 16],
[13, 9, 3]]]])
tensor([[[[ 1, 3, 4, 10, 8],
[ 5, 10, 12, 12, 6],
[ 7, 18, 16, 16, 8],
[11, 13, 9, 3, 4],
[14, 13, 9, 7, 4]]]])Process finished with exit code 0
- import torch
- import torchvision
- from torch import nn
- from torch.nn import Conv2d
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
-
- dataset = torchvision.datasets.CIFAR10("./data_conv2d", train=False, transform=torchvision.transforms.ToTensor(),
- download=True)
- dataloader = DataLoader(dataset, batch_size=64)
-
- class Jzh(nn.Module):
- def __init__(self):
- super(Jzh, self).__init__()
- # out_channels实际上就是卷积核的数量,有多少个卷积之后就输出几幅图像
- 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
-
- jzh = Jzh()
- print(jzh)
-
- writer = SummaryWriter("./logs")
- step = 0
- for data in dataloader:
- imgs, targets = data
- output = jzh(imgs)
- print(imgs.shape)
- print(output.shape)
- # 输入时的大小:torch.Size([64, 3, 32, 32])
- writer.add_images("input", imgs, step)
-
- # torch.Size([64, 6, 30, 30]) -> [xxx, 3, 30, 30]
- # 3保证输出的仍是三维的数据与输入时一致,这样就能正常显示输出图像
- output = torch.reshape(output, (-1, 3, 30, 30))
- # 输出时的大小:
- writer.add_images("output", output, step)
- step = step + 1
- writer.close()
-
[i]
- import torch
- from torch import nn
- from torch.nn import MaxPool2d
-
- input = torch.tensor([[1, 2, 0, 3, 1],
- [0, 1, 2, 3, 1],
- [1, 2, 1, 0, 0],
- [5, 2, 3, 1, 1],
- [2, 1, 0, 1, 1]], dtype=torch.float32)
-
- # -1表示自动计算batch_size;1表示一个channel;5、5表示5*5的输入图像
- # batch size(批量大小)是一个超参数,它指的是在进行模型训练或评估时,每次迭代所使用的数据样本的数量。
- input = torch.reshape(input, (-1, 1, 5, 5))
- print(input.shape)
-
- class Jzh(nn.Module):
- def __init__(self):
- super(Jzh, self).__init__()
- # ceil_mode表示不足三列或者三行的按照三行然后去池中的最大值
- self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)
-
- def forward(self, input):
- output = self.maxpool1(input)
- return output
-
- jzh = Jzh()
- output = jzh(input)
- print(output)
-
经池化后输出为:
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\nn_maxpool.py
torch.Size([1, 1, 5, 5])
tensor([[[[2., 3.],
[5., 1.]]]])Process finished with exit code 0
加载CIRF10数据集进行池化操作:
- import torch
- import torchvision
- from torch import nn
- from torch.nn import MaxPool2d
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
-
- dataset = torchvision.datasets.CIFAR10("./data_pool", train=False, download=True,
- transform=torchvision.transforms.ToTensor())
-
- dataloader = DataLoader(dataset, batch_size=64)
- # 用于创建一个数据加载器(DataLoader),它将数据集(dataset)分成大小为64的批次。
-
- class Jzh(nn.Module):
- def __init__(self):
- super(Jzh, self).__init__()
- # ceil_mode表示不足三列或者三行的按照三行然后去池中的最大值
- self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)
-
- def forward(self, input):
- output = self.maxpool1(input)
- return output
-
- jzh = Jzh()
-
- writer = SummaryWriter("logs_maxpool")
- step = 0
- for data in dataloader:
- imgs, targets = data
- writer.add_images("input", imgs, step)
- output = jzh(imgs)
- writer.add_images("output", output, step)
- step = step+1
-
- writer.close()
-
[i]
- import torch
- import torchvision
- from torch import nn
- from torch.nn import ReLU, Sigmoid
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
-
- input = torch.tensor([[1, -0.5],
- [-1, 3]])
- input = torch.reshape(input, (-1, 1, 2, 2))
- print(input.shape)
-
- dataset = torchvision.datasets.CIFAR10("./data_pool", train=False, download=True,
- transform=torchvision.transforms.ToTensor())
- dataloader = DataLoader(dataset, batch_size=64)
- class Jzh(nn.Module):
- def __init__(self):
- super().__init__()
- self.relu1 = ReLU()
- self.sigmoid1 = Sigmoid()
-
-
- def forward(self, input):
- # 将输入的实数值映射到介于0和1之间的输出
- output = self.sigmoid1(input)
- return output
-
- jzh=Jzh()
- writer = SummaryWriter("logs_sigmoid1")
- step = 0
- for data in dataloader:
- imgs, targets = data
- writer.add_images("input", imgs, global_step=step)
- output = jzh(imgs)
- writer.add_images("output", output, step)
- step = step+1
-
- writer.close()
-
激活函数向图像引入非线性特征:
[i]
- import torch
- import torchvision
- from torch import nn
- from torch.nn import Linear
- from torch.utils.data import DataLoader
-
- dataset = torchvision.datasets.CIFAR10("./data_linear", train=False, transform=torchvision.transforms.ToTensor(),
- download=True)
- dataloader = DataLoader(dataset, batch_size=64, drop_last=True)
-
- class Jzh(nn.Module):
- def __init__(self):
- super().__init__()
- # 将图片展平成torch.Size([1, 1, 1, 196608])格式
- self.linear1 = Linear(196608, 10)
-
- def forward(self, input):
- output = self.linear1(input)
- return output
-
- jzh = Jzh()
-
- for data in dataloader:
- imgs, target = data
- print(imgs.shape)
- # output = torch.reshape(imgs, (1, 1, 1, -1))
- # 上述代码可以由下一行代码替换,并直接输出成torch.Size([196608])
- output =torch.flatten(imgs)
- print(output.shape)
- output = jzh(output)
- print(output.shape)
-
Inputs -> 第一层Feature maps 层的计算可由如下公式得出:
[i]
计算过程为:
[ 32 + 2padding - 1(5-1) - 1 ] / stride + 1 = 32 , 得出padding=2,stride=1
对应代码为:self.conv1 = Conv2d(3, 32, 5, padding=2)
- import torch
- from torch import nn
- from torch.nn import MaxPool2d, Flatten, Linear, Conv2d, Sequential
- from torch.utils.tensorboard import SummaryWriter
-
-
- class Jzh(nn.Module):
- def __init__(self):
- super().__init__()
- # 第一种写法
- # self.conv1 = Conv2d(3, 32, 5, padding=2)
- # self.maxpool1 = MaxPool2d(2)
- # self.conv2 = Conv2d(32, 32, 5, padding=2)
- # self.maxpool2 = MaxPool2d(2)
- # self.conv3 = Conv2d(32, 64, 5, padding=2)
- # self.maxpool3 = MaxPool2d(2)
- # 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
-
- jzh = Jzh()
- print(jzh)
- # torch.ones((64, 3, 32, 32))里的参数注意和Conv2d(32, 32, 5, padding=2)作区分,这里的64指batch_size
- input = torch.ones((64, 3, 32, 32))
- output = jzh(input)
- # 检验输出结果是否为torch.Size([64, 10]),因为这是一个是分类的模型,若是则证明self.linear2 = Linear(64, 10)正常执行
- print(output.shape)
-
-
- writer = SummaryWriter("./logs_seq")
- # jzh 是一个 PyTorch 模型,input 是输入数据,这个函数会将模型的计算图添加到 TensorBoard,以便在可视化时查看模型的结构
- writer.add_graph(jzh, input)
- writer.close()
-
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\nn_CIFAR10.py
Jzh(
(model1): Sequential(
(0): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(4): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(6): Flatten(start_dim=1, end_dim=-1)
(7): Linear(in_features=1024, out_features=64, bias=True)
(8): Linear(in_features=64, out_features=10, bias=True)
)
)
torch.Size([64, 10])Process finished with exit code 0
模型结构图:
[i]
LogSoftmax用于计算log-softmax激活。它的作用是将输入张量中的每个元素进行指数运算后归一化,然后取对数。这样可以将原始输出转换为概率分布,便于在分类任务中使用
计算公式如下:
注意,深度学习中的log默认是以e为底的即ln
- import torch
- from torch import nn
- from torch.nn import L1Loss, MSELoss
-
- 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))
-
- loss = L1Loss()
- # result=(0+0+2)/3
- result = loss(inputs, targets)
-
- loss_mse = MSELoss()
- result_mse = loss_mse(inputs, targets)
-
- print(result)
- print(result_mse)
-
- x = torch.tensor([0.1, 0.2, 0.3])
- y = torch.tensor([1])
- x = torch.reshape(x, (1, 3))
- loss_cross = nn.CrossEntropyLoss()
- result_cross = loss_cross(x, y)
- print(result_cross)
-
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\nn_loss.py
tensor(0.6667)
tensor(1.3333)
tensor(1.1019)Process finished with exit code 0
计算实际输出和目标之间的差距
- import torch
- import torchvision
- from torch import nn
- from torch.nn import MaxPool2d, Flatten, Linear, Conv2d, Sequential
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
-
- dataset = torchvision.datasets.CIFAR10("./data_linear", train=False, transform=torchvision.transforms.ToTensor(),
- download=True)
- dataloader = DataLoader(dataset, batch_size=1)
-
-
- class Jzh(nn.Module):
- def __init__(self):
- super().__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
-
- loss = nn.CrossEntropyLoss()
- jzh = Jzh()
- for data in dataloader:
- imgs, targets = data
- outputs = jzh(imgs)
- result_loss = loss(outputs, targets)
- print(result_loss)
-
部分输出结果:
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\nn_loss_network.py
Files already downloaded and verified
tensor(2.3428, grad_fn=<NllLossBackward0>)
tensor(2.3684, grad_fn=<NllLossBackward0>)
tensor(2.3722, grad_fn=<NllLossBackward0>)
tensor(2.3924, grad_fn=<NllLossBackward0>)
tensor(2.3649, grad_fn=<NllLossBackward0>)
tensor(2.3878, grad_fn=<NllLossBackward0>)
tensor(2.1113, grad_fn=<NllLossBackward0>)
为我们更新输出提供一定的依据:反向传播and优化器
主体部分不变,在上述代码中增加如下sgd优化器代码:
- loss = nn.CrossEntropyLoss()
- jzh = Jzh()
- # lr为学习速率,一般模型训练开始时设置较大,模型训练后期设置较小
- optim = torch.optim.SGD(jzh.parameters(), 0.01)
- for epoch in range(20):
- running_loss = 0.0
- # 下面这个for仅代表循环一次
- for data in dataloader:
- imgs, targets = data
- outputs = jzh(imgs)
- result_loss = loss(outputs, targets)
- # 清零梯度
- optim.zero_grad()
- # 计算每个节点参数的梯度,方便后续用优化器对其优化
- result_loss.backward()
- optim.step()
- # 这一轮整体误差总和
- running_loss = running_loss + result_loss
- print(running_loss)
-
部分运行结果:
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\nn_optim.py
Files already downloaded and verified
tensor(18591.2637, grad_fn=<AddBackward0>)
tensor(16061.7539, grad_fn=<AddBackward0>)
tensor(15454.4775, grad_fn=<AddBackward0>)
tensor(15985.7441, grad_fn=<AddBackward0>)
tensor(18142.6211, grad_fn=<AddBackward0>)
tensor(20303.0449, grad_fn=<AddBackward0>)
tensor(22268.1523, grad_fn=<AddBackward0>)
tensor(23856.8047, grad_fn=<AddBackward0>)
tensor(25047.0723, grad_fn=<AddBackward0>)
- import torchvision
- from torchvision.models import VGG16_Weights
- from torch import nn
-
- # train_data = torchvision.datasets.ImageNet("./data_imagenet", split='train', download=True,
- # transform=torchvision.transforms.ToTensor())
-
- # vgg16_false = torchvision.models.vgg16(pretrained=False)
- # 设置成true则下载的是一个已经预训练过的模型
- # vgg16_true = torchvision.models.vgg16(pretrained=True)
- # 下列语句为新版本模型加载代码,新版本默认没有预训练,如需预训练则需加上weights=VGG16_Weights.DEFAULT
- vgg16_true = torchvision.models.vgg16(weights=VGG16_Weights.DEFAULT)
- print(vgg16_true)
-
- train_data = torchvision.datasets.CIFAR10("./dataset", train=True, transform=torchvision.transforms.ToTensor(),
- download=True)
- # 对模型进行修改,从1000分类修改成10分类
- vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
- print(vgg16_true)
-
VGG1000分类和10分类输出对比:
VGG(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(6): ReLU(inplace=True)
(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(8): ReLU(inplace=True)
(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(11): ReLU(inplace=True)
(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(13): ReLU(inplace=True)
(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(15): ReLU(inplace=True)
(16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(18): ReLU(inplace=True)
(19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(20): ReLU(inplace=True)
(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(22): ReLU(inplace=True)
(23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(25): ReLU(inplace=True)
(26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(27): ReLU(inplace=True)
(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(29): ReLU(inplace=True)
(30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
(classifier): Sequential(
(0): Linear(in_features=25088, out_features=4096, bias=True)
(1): ReLU(inplace=True)
(2): Dropout(p=0.5, inplace=False)
(3): Linear(in_features=4096, out_features=4096, bias=True)
(4): ReLU(inplace=True)
(5): Dropout(p=0.5, inplace=False)
(6): Linear(in_features=4096, out_features=1000, bias=True)
)
)
改成10分类则在(6): Linear(in_features=4096, out_features=1000, bias=True)之后多添加了一层线性层:
(add_linear): Linear(in_features=1000, out_features=10, bias=True)
model_save
- import torch
- import torchvision
- from torch import nn
-
- vgg16 = torchvision.models.vgg16(weights=None)
- # 第一种保存方式,模型结构+模型参数
- torch.save(vgg16, "vgg16_method1.pth")
-
- # 第二种保存方式,模型参数(保存成字典形式),官方推荐,但这样输出的就不再是一个网络模型了,需要使用还要进行相关操作
- torch.save(vgg16.state_dict(), "vgg16_method2.pth")
-
- # 方式一有陷阱(如果自己搭建模型的话)
- class Jzh(nn.Module):
- def __init__(self):
- super(Jzh, self).__init__()
- self.conv1 = nn.Conv2d(3, 64, kernel_size=3)
-
- def forward(self, x):
- x = self.conv1(x)
- return x
-
- jzh = Jzh()
- torch.save(jzh, "jzh_method1.pth")
-
model_load
- import torch
- import torchvision
- from model_save import *
- from torch import nn
-
- # 对应方式1,加载模型
- model = torch.load("vgg16_method1.pth")
- # print(model)
-
- # 对应方式2,加载模型
- vgg16 = torchvision.models.vgg16(weights=None)
- vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
- # model = torch.load("vgg16_method2.pth")
- print(vgg16)
-
- # 方式一陷阱,自己创建的模型需要在这里定义一下,但是from model_save import *下面代码就可以不要了,
- # model_save文件定义过了,直接加载模型打印
- # class Jzh(nn.Module):
- # def __init__(self):
- # super(Jzh, self).__init__()
- # self.conv1 = nn.Conv2d(3, 64, kernel_size=3)
- #
- # def forward(self, x):
- # x = self.conv1(x)
- # return x
-
- model = torch.load('jzh_method1.pth')
- print(model)
- import torch
-
- import torchvision
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
-
- from model import *
-
- # 准备数据集
- train_data = torchvision.datasets.CIFAR10(root="./data_taolu", train=True, transform=torchvision.transforms.ToTensor(),
- download=True)
- test_data = torchvision.datasets.CIFAR10(root="./data_taolu", train=False, transform=torchvision.transforms.ToTensor(),
- download=True)
-
- train_data_size = len(train_data)
- test_data_size = len(test_data)
- print("训练数据集的长度为:{}".format(train_data_size))
- print("测试数据集的长度为:{}".format(test_data_size))
-
- # 利用DataLoader来加载数据集
- train_dataloader = DataLoader(train_data, batch_size=64)
- test_dataloader = DataLoader(test_data, batch_size=64)
-
- # 创建网络模型
- jzh = Jzh()
-
- # 创建损失函数
- loss_fn = nn.CrossEntropyLoss()
-
- # 优化器
- # learning_rate = 0.01
- # 1e-2=1 x (10)^(-2) = 1/100 = 0.01
- learning_rate = 1e-2
- optimizer = torch.optim.SGD(jzh.parameters(), lr=learning_rate)
-
- # 设置网络的一些参数
- # 记录训练次数
- total_train_step = 0
- # 记录测试次数
- total_test_step = 0
- # 记录训练的轮数
- epoch = 10
-
- # 添加tensorboard
- writer = SummaryWriter("./logs_train")
-
- for i in range(epoch):
- print("------第 {} 轮训练开始------".format(i+1))
- # 训练步骤开始
- jzh.train()
- for data in train_dataloader:
- imgs, targets = data
- outputs = jzh(imgs)
- loss = loss_fn(outputs, targets)
-
- # 优化器调优
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
-
- total_train_step = total_train_step + 1
- if total_train_step % 100 == 0:
- print("训练次数: {}, loss: {}".format(total_train_step, loss.item()))
- writer.add_scalar("train_loss", loss.item(), total_train_step)
-
- # 测试步骤开始
- jzh.eval()
- total_test_loss = 0
- total_accuracy = 0
- with torch.no_grad():
- for data in test_dataloader:
- imgs, targets = data
- outputs = jzh(imgs)
- loss = loss_fn(outputs, targets)
- total_test_loss = total_test_loss + loss.item()
- accuracy = (outputs.argmax(1) == targets).sum()
- total_accuracy = total_accuracy + accuracy
- print("整体测试集上的loss: {}".format(total_test_loss))
- print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size))
- writer.add_scalar("test_loss", total_test_loss, total_test_step)
- writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
- total_test_step = total_test_step + 1
-
- # 保存模型
- torch.save(jzh, "jzh_{}.pth".format(i))
- print("模型已保存")
- writer.close()
-
- import torch
- from torch import nn
-
- # 搭建神经网络
- class Jzh(nn.Module):
- def __init__(self):
- super(Jzh, self).__init__()
- self.model = nn.Sequential(
- nn.Conv2d(3, 32, 5, 1, padding=2),
- nn.MaxPool2d(2),
- nn.Conv2d(32, 32, 5, 1, padding=2),
- nn.MaxPool2d(2),
- nn.Conv2d(32, 64, 5, 1, padding=2),
- nn.MaxPool2d(2),
- nn.Flatten(),
- nn.Linear(1024, 64),
- nn.Linear(64, 10)
- )
-
- def forward(self, x):
- x = self.model(x)
- return x
-
-
- if __name__ == '__main__':
- jzh = Jzh()
- input = torch.ones((64, 3, 32, 32))
- output = jzh(input)
- print(output.shape)
-
部分输出结果:
训练数据集的长度为:50000
测试数据集的长度为:10000
------第 1 轮训练开始------
训练次数: 100, loss: 2.2846009731292725
训练次数: 200, loss: 2.2844748497009277
训练次数: 300, loss: 2.2514917850494385
训练次数: 400, loss: 2.148555278778076
训练次数: 500, loss: 2.1040234565734863
训练次数: 600, loss: 2.033297061920166
训练次数: 700, loss: 1.9678012132644653
整体测试集上的loss: 320.23996794223785
整体测试集上的正确率: 0.26930001378059387
模型已保存
------第 2 轮训练开始------
训练次数: 800, loss: 1.8451868295669556
训练次数: 900, loss: 1.8664506673812866
训练次数: 1000, loss: 1.905165433883667
训练次数: 1100, loss: 1.979297161102295
训练次数: 1200, loss: 1.6892757415771484
训练次数: 1300, loss: 1.655542254447937
训练次数: 1400, loss: 1.725655436515808
训练次数: 1500, loss: 1.8056442737579346
整体测试集上的loss: 287.658221244812
整体测试集上的正确率: 0.3418999910354614
模型已保存
模型tensorboard图:
[i]
[i]
[i]
总结来说,完整的模型训练套路为:准备数据,加载数据,准备模型,设置损失函数,设置优化器,开始训练,最后验证,结果聚合展示
- import torch
- import torchvision
- from PIL import Image
- from torch import nn
-
- image_path = "./imgs/airplan.png"
- image = Image.open(image_path)
- # 保留颜色通道,加上这一步后可以适应png、jpg各种格式图片
- # image = image.convert('RGB')
- print(image)
-
- transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
- torchvision.transforms.ToTensor()])
-
- image = transform(image)
- print(image.shape)
-
- class Jzh(nn.Module):
- def __init__(self):
- super(Jzh, self).__init__()
- self.model = nn.Sequential(
- nn.Conv2d(3, 32, 5, 1, padding=2),
- nn.MaxPool2d(2),
- nn.Conv2d(32, 32, 5, 1, padding=2),
- nn.MaxPool2d(2),
- nn.Conv2d(32, 64, 5, 1, padding=2),
- nn.MaxPool2d(2),
- nn.Flatten(),
- nn.Linear(1024, 64),
- nn.Linear(64, 10)
- )
-
- def forward(self, x):
- x = self.model(x)
- return x
-
- model = torch.load("./jzh_9.pth")
- # 若使用GPU训练的模型,一定要使用下述语句将其映射到CPU上
- # model = torch.load("jzh_gpu.pth" ,map_location=torch.device('cpu'))
- print(model)
- # 数据要和模型一致
- image = torch.reshape(image, (1, 3, 32, 32))
- model.eval()
- with torch.no_grad():
- output = model(image)
- print(output)
-
如图为CIFAR10数据集对应的物体类别:
[i]
如下为预测结果:
D:\software\anaconda\Ana\envs\pycyy\python.exe D:\code\Python\pycyy\test.py
<PIL.PngImagePlugin.PngImageFile image mode=RGB size=295x183 at 0x21FE599AC08>
torch.Size([3, 32, 32])
Jzh(
(model): Sequential(
(0): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(4): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(6): Flatten(start_dim=1, end_dim=-1)
(7): Linear(in_features=1024, out_features=64, bias=True)
(8): Linear(in_features=64, out_features=10, bias=True)
)
)
tensor([[10.5353, 1.8883, 1.5429, -2.5516, 0.0149, -4.7008, -5.5488, -5.0510,
3.8907, -1.5681]])
tensor([0])Process finished with exit code 0
其中airplan对应类别下标为00,其预测概率最大,模型预测正确
后续将继续学习github上优秀的开源项目,加油!!!
Author:####Jzh##
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。