├── .gitignore ├── imgs └── weixin.jpg ├── src ├── tudui_0.pth ├── tudui_29_gpu.pth ├── nn_module.py ├── P8_Tensorboard.py ├── model_save.py ├── nn_loss.py ├── model_load.py ├── nn_conv.py ├── model.py ├── P10_dataset_transform.py ├── dataloader.py ├── model_pretrained.py ├── nn_linear.py ├── nn_seq.py ├── nn_maxpool.py ├── nn_loss_network.py ├── nn_relu.py ├── nn_conv2d.py ├── test.py ├── nn_optim.py ├── P9_transforms.py ├── read_data.py ├── train.py ├── train-cpu.py ├── train_gpu_2.py └── train_gpu_1.py └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /logs 3 | /data 4 | /logs_* -------------------------------------------------------------------------------- /imgs/weixin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotudui/pytorch-tutorial/HEAD/imgs/weixin.jpg -------------------------------------------------------------------------------- /src/tudui_0.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotudui/pytorch-tutorial/HEAD/src/tudui_0.pth -------------------------------------------------------------------------------- /src/tudui_29_gpu.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotudui/pytorch-tutorial/HEAD/src/tudui_29_gpu.pth -------------------------------------------------------------------------------- /src/nn_module.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | from torch import nn 6 | 7 | 8 | class Tudui(nn.Module): 9 | def __init__(self): 10 | super().__init__() 11 | 12 | def forward(self, input): 13 | output = input + 1 14 | return output 15 | 16 | 17 | tudui = Tudui() 18 | x = torch.tensor(1.0) 19 | output = tudui(x) 20 | print(output) -------------------------------------------------------------------------------- /src/P8_Tensorboard.py: -------------------------------------------------------------------------------- 1 | from torch.utils.tensorboard import SummaryWriter 2 | import numpy as np 3 | from PIL import Image 4 | 5 | writer = SummaryWriter("logs") 6 | image_path = "data/train/ants_image/6240329_72c01e663e.jpg" 7 | img_PIL = Image.open(image_path) 8 | img_array = np.array(img_PIL) 9 | print(type(img_array)) 10 | print(img_array.shape) 11 | 12 | writer.add_image("train", img_array, 1, dataformats='HWC') 13 | # y = 2x 14 | for i in range(100): 15 | writer.add_scalar("y=2x", 3*i, i) 16 | 17 | writer.close() -------------------------------------------------------------------------------- /src/model_save.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | import torchvision 6 | from torch import nn 7 | 8 | vgg16 = torchvision.models.vgg16(pretrained=False) 9 | # 保存方式1,模型结构+模型参数 10 | torch.save(vgg16, "vgg16_method1.pth") 11 | 12 | # 保存方式2,模型参数(官方推荐) 13 | torch.save(vgg16.state_dict(), "vgg16_method2.pth") 14 | 15 | # 陷阱 16 | class Tudui(nn.Module): 17 | def __init__(self): 18 | super(Tudui, self).__init__() 19 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3) 20 | 21 | def forward(self, x): 22 | x = self.conv1(x) 23 | return x 24 | 25 | tudui = Tudui() 26 | torch.save(tudui, "tudui_method1.pth") -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pytorch教程 2 | 3 | 相信尝试找到此教程的你,已经知道 PyTorch 的用途。 4 | 5 | 找到此教程的你,也许跟我一样,尝试过各种教程,官方的教程文档,各色的视频,但发现都不是很友好。 6 | 7 | 所以机缘巧合下,录制了这个视频。 8 | 9 | 10 | ## 如何使用 11 | 12 | 本系列教程,致力于打造成为通俗易懂的教程。所以课程安排的思路也是比较特点,相信一定能让你快速入门。 13 | 14 | 本文提供视频版(已完结)。2021 年完结。 15 | 16 | **视频中涉及的代码均在src文件夹中。** 17 | 18 | 19 | 视频版:https://www.bilibili.com/video/av74281036/ 20 | 21 | 22 | ## 后续规划 & 进阶 23 | 24 | 写于 2025年12月。 25 | 26 | 最近录制了新的视频教程,目前检测入门教程。 27 | 28 | 可以看作是 PyTorch 入门教程后续的实战或者进阶教程。正在努力更新中... 29 | 30 | https://www.bilibili.com/video/BV19Z31z8ENH/ 31 | 32 | 33 | 其实,我还有很多的课程想法以及一些奇怪的课程规划,但对于一个拖延症患者而言,先努力保持更新才是最重要的 :) 34 | 35 | 如果你对此还挺期待的,可以关注公众号【我是土堆】,到时候我会在上面更新些有意思的东西。(很久很久没写文章了,上一篇还是几年前。) 36 | 37 | ![](./imgs/weixin.jpg) 38 | 39 | -------------------------------------------------------------------------------- /src/nn_loss.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | from torch.nn import L1Loss 6 | from torch import nn 7 | 8 | inputs = torch.tensor([1, 2, 3], dtype=torch.float32) 9 | targets = torch.tensor([1, 2, 5], dtype=torch.float32) 10 | 11 | inputs = torch.reshape(inputs, (1, 1, 1, 3)) 12 | targets = torch.reshape(targets, (1, 1, 1, 3)) 13 | 14 | loss = L1Loss(reduction='sum') 15 | result = loss(inputs, targets) 16 | 17 | loss_mse = nn.MSELoss() 18 | result_mse = loss_mse(inputs, targets) 19 | 20 | print(result) 21 | print(result_mse) 22 | 23 | 24 | x = torch.tensor([0.1, 0.2, 0.3]) 25 | y = torch.tensor([1]) 26 | x = torch.reshape(x, (1, 3)) 27 | loss_cross = nn.CrossEntropyLoss() 28 | result_cross = loss_cross(x, y) 29 | print(result_cross) -------------------------------------------------------------------------------- /src/model_load.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | from model_save import * 6 | # 方式1-》保存方式1,加载模型 7 | import torchvision 8 | from torch import nn 9 | 10 | model = torch.load("vgg16_method1.pth") 11 | # print(model) 12 | 13 | # 方式2,加载模型 14 | vgg16 = torchvision.models.vgg16(pretrained=False) 15 | vgg16.load_state_dict(torch.load("vgg16_method2.pth")) 16 | # model = torch.load("vgg16_method2.pth") 17 | # print(vgg16) 18 | 19 | # 陷阱1 20 | # class Tudui(nn.Module): 21 | # def __init__(self): 22 | # super(Tudui, self).__init__() 23 | # self.conv1 = nn.Conv2d(3, 64, kernel_size=3) 24 | # 25 | # def forward(self, x): 26 | # x = self.conv1(x) 27 | # return x 28 | 29 | model = torch.load('tudui_method1.pth') 30 | print(model) -------------------------------------------------------------------------------- /src/nn_conv.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | 5 | import torch 6 | import torch.nn.functional as F 7 | 8 | input = torch.tensor([[1, 2, 0, 3, 1], 9 | [0, 1, 2, 3, 1], 10 | [1, 2, 1, 0, 0], 11 | [5, 2, 3, 1, 1], 12 | [2, 1, 0, 1, 1]]) 13 | 14 | kernel = torch.tensor([[1, 2, 1], 15 | [0, 1, 0], 16 | [2, 1, 0]]) 17 | 18 | input = torch.reshape(input, (1, 1, 5, 5)) 19 | kernel = torch.reshape(kernel, (1, 1, 3, 3)) 20 | 21 | print(input.shape) 22 | print(kernel.shape) 23 | 24 | output = F.conv2d(input, kernel, stride=1) 25 | print(output) 26 | 27 | output2 = F.conv2d(input, kernel, stride=2) 28 | print(output2) 29 | 30 | output3 = F.conv2d(input, kernel, stride=1, padding=1) 31 | print(output3) 32 | 33 | -------------------------------------------------------------------------------- /src/model.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | from torch import nn 6 | 7 | # 搭建神经网络 8 | class Tudui(nn.Module): 9 | def __init__(self): 10 | super(Tudui, self).__init__() 11 | self.model = nn.Sequential( 12 | nn.Conv2d(3, 32, 5, 1, 2), 13 | nn.MaxPool2d(2), 14 | nn.Conv2d(32, 32, 5, 1, 2), 15 | nn.MaxPool2d(2), 16 | nn.Conv2d(32, 64, 5, 1, 2), 17 | nn.MaxPool2d(2), 18 | nn.Flatten(), 19 | nn.Linear(64*4*4, 64), 20 | nn.Linear(64, 10) 21 | ) 22 | 23 | def forward(self, x): 24 | x = self.model(x) 25 | return x 26 | 27 | 28 | if __name__ == '__main__': 29 | tudui = Tudui() 30 | input = torch.ones((64, 3, 32, 32)) 31 | output = tudui(input) 32 | print(output.shape) -------------------------------------------------------------------------------- /src/P10_dataset_transform.py: -------------------------------------------------------------------------------- 1 | import torchvision 2 | from torch.utils.tensorboard import SummaryWriter 3 | 4 | dataset_transform = torchvision.transforms.Compose([ 5 | torchvision.transforms.ToTensor() 6 | ]) 7 | 8 | train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, transform=dataset_transform, download=True) 9 | test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, transform=dataset_transform, download=True) 10 | 11 | # print(test_set[0]) 12 | # print(test_set.classes) 13 | # 14 | # img, target = test_set[0] 15 | # print(img) 16 | # print(target) 17 | # print(test_set.classes[target]) 18 | # img.show() 19 | # 20 | # print(test_set[0]) 21 | 22 | writer = SummaryWriter("p10") 23 | for i in range(10): 24 | img, target = test_set[i] 25 | writer.add_image("test_set", img, i) 26 | 27 | writer.close() -------------------------------------------------------------------------------- /src/dataloader.py: -------------------------------------------------------------------------------- 1 | import torchvision 2 | 3 | # 准备的测试数据集 4 | from torch.utils.data import DataLoader 5 | from torch.utils.tensorboard import SummaryWriter 6 | 7 | test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor()) 8 | 9 | test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True) 10 | 11 | # 测试数据集中第一张图片及target 12 | img, target = test_data[0] 13 | print(img.shape) 14 | print(target) 15 | 16 | writer = SummaryWriter("dataloader") 17 | for epoch in range(2): 18 | step = 0 19 | for data in test_loader: 20 | imgs, targets = data 21 | # print(imgs.shape) 22 | # print(targets) 23 | writer.add_images("Epoch: {}".format(epoch), imgs, step) 24 | step = step + 1 25 | 26 | writer.close() 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/model_pretrained.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torchvision 5 | 6 | # train_data = torchvision.datasets.ImageNet("../data_image_net", split='train', download=True, 7 | # transform=torchvision.transforms.ToTensor()) 8 | from torch import nn 9 | 10 | vgg16_false = torchvision.models.vgg16(pretrained=False) 11 | vgg16_true = torchvision.models.vgg16(pretrained=True) 12 | 13 | print(vgg16_true) 14 | 15 | train_data = torchvision.datasets.CIFAR10('../data', train=True, transform=torchvision.transforms.ToTensor(), 16 | download=True) 17 | 18 | vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10)) 19 | print(vgg16_true) 20 | 21 | print(vgg16_false) 22 | vgg16_false.classifier[6] = nn.Linear(4096, 10) 23 | print(vgg16_false) 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/nn_linear.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | import torchvision 6 | from torch import nn 7 | from torch.nn import Linear 8 | from torch.utils.data import DataLoader 9 | 10 | dataset = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(), 11 | download=True) 12 | 13 | dataloader = DataLoader(dataset, batch_size=64, drop_last=True) 14 | 15 | class Tudui(nn.Module): 16 | def __init__(self): 17 | super(Tudui, self).__init__() 18 | self.linear1 = Linear(196608, 10) 19 | 20 | def forward(self, input): 21 | output = self.linear1(input) 22 | return output 23 | 24 | tudui = Tudui() 25 | 26 | for data in dataloader: 27 | imgs, targets = data 28 | print(imgs.shape) 29 | output = torch.flatten(imgs) 30 | print(output.shape) 31 | output = tudui(output) 32 | print(output.shape) 33 | -------------------------------------------------------------------------------- /src/nn_seq.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | from torch import nn 6 | from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential 7 | from torch.utils.tensorboard import SummaryWriter 8 | 9 | 10 | class Tudui(nn.Module): 11 | def __init__(self): 12 | super(Tudui, self).__init__() 13 | self.model1 = Sequential( 14 | Conv2d(3, 32, 5, padding=2), 15 | MaxPool2d(2), 16 | Conv2d(32, 32, 5, padding=2), 17 | MaxPool2d(2), 18 | Conv2d(32, 64, 5, padding=2), 19 | MaxPool2d(2), 20 | Flatten(), 21 | Linear(1024, 64), 22 | Linear(64, 10) 23 | ) 24 | 25 | def forward(self, x): 26 | x = self.model1(x) 27 | return x 28 | 29 | tudui = Tudui() 30 | print(tudui) 31 | input = torch.ones((64, 3, 32, 32)) 32 | output = tudui(input) 33 | print(output.shape) 34 | 35 | writer = SummaryWriter("../logs_seq") 36 | writer.add_graph(tudui, input) 37 | writer.close() 38 | -------------------------------------------------------------------------------- /src/nn_maxpool.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | 5 | import torch 6 | import torchvision 7 | from torch import nn 8 | from torch.nn import MaxPool2d 9 | from torch.utils.data import DataLoader 10 | from torch.utils.tensorboard import SummaryWriter 11 | 12 | dataset = torchvision.datasets.CIFAR10("../data", train=False, download=True, 13 | transform=torchvision.transforms.ToTensor()) 14 | 15 | dataloader = DataLoader(dataset, batch_size=64) 16 | 17 | class Tudui(nn.Module): 18 | def __init__(self): 19 | super(Tudui, self).__init__() 20 | self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=False) 21 | 22 | def forward(self, input): 23 | output = self.maxpool1(input) 24 | return output 25 | 26 | tudui = Tudui() 27 | 28 | writer = SummaryWriter("../logs_maxpool") 29 | step = 0 30 | 31 | for data in dataloader: 32 | imgs, targets = data 33 | writer.add_images("input", imgs, step) 34 | output = tudui(imgs) 35 | writer.add_images("output", output, step) 36 | step = step + 1 37 | 38 | writer.close() -------------------------------------------------------------------------------- /src/nn_loss_network.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torchvision 5 | from torch import nn 6 | from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear 7 | from torch.utils.data import DataLoader 8 | 9 | dataset = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(), 10 | download=True) 11 | 12 | dataloader = DataLoader(dataset, batch_size=1) 13 | 14 | class Tudui(nn.Module): 15 | def __init__(self): 16 | super(Tudui, self).__init__() 17 | self.model1 = Sequential( 18 | Conv2d(3, 32, 5, padding=2), 19 | MaxPool2d(2), 20 | Conv2d(32, 32, 5, padding=2), 21 | MaxPool2d(2), 22 | Conv2d(32, 64, 5, padding=2), 23 | MaxPool2d(2), 24 | Flatten(), 25 | Linear(1024, 64), 26 | Linear(64, 10) 27 | ) 28 | 29 | def forward(self, x): 30 | x = self.model1(x) 31 | return x 32 | 33 | 34 | loss = nn.CrossEntropyLoss() 35 | tudui = Tudui() 36 | for data in dataloader: 37 | imgs, targets = data 38 | outputs = tudui(imgs) 39 | result_loss = loss(outputs, targets) 40 | print("ok") 41 | -------------------------------------------------------------------------------- /src/nn_relu.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | import torchvision 6 | from torch import nn 7 | from torch.nn import ReLU, Sigmoid 8 | from torch.utils.data import DataLoader 9 | from torch.utils.tensorboard import SummaryWriter 10 | 11 | input = torch.tensor([[1, -0.5], 12 | [-1, 3]]) 13 | 14 | input = torch.reshape(input, (-1, 1, 2, 2)) 15 | print(input.shape) 16 | 17 | dataset = torchvision.datasets.CIFAR10("../data", train=False, download=True, 18 | transform=torchvision.transforms.ToTensor()) 19 | 20 | dataloader = DataLoader(dataset, batch_size=64) 21 | 22 | class Tudui(nn.Module): 23 | def __init__(self): 24 | super(Tudui, self).__init__() 25 | self.relu1 = ReLU() 26 | self.sigmoid1 = Sigmoid() 27 | 28 | def forward(self, input): 29 | output = self.sigmoid1(input) 30 | return output 31 | 32 | tudui = Tudui() 33 | 34 | writer = SummaryWriter("../logs_relu") 35 | step = 0 36 | for data in dataloader: 37 | imgs, targets = data 38 | writer.add_images("input", imgs, global_step=step) 39 | output = tudui(imgs) 40 | writer.add_images("output", output, step) 41 | step += 1 42 | 43 | writer.close() 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/nn_conv2d.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | import torchvision 6 | from torch import nn 7 | from torch.nn import Conv2d 8 | from torch.utils.data import DataLoader 9 | from torch.utils.tensorboard import SummaryWriter 10 | 11 | dataset = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(), 12 | download=True) 13 | dataloader = DataLoader(dataset, batch_size=64) 14 | 15 | class Tudui(nn.Module): 16 | def __init__(self): 17 | super(Tudui, self).__init__() 18 | self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0) 19 | 20 | def forward(self, x): 21 | x = self.conv1(x) 22 | return x 23 | 24 | tudui = Tudui() 25 | 26 | writer = SummaryWriter("../logs") 27 | 28 | step = 0 29 | for data in dataloader: 30 | imgs, targets = data 31 | output = tudui(imgs) 32 | print(imgs.shape) 33 | print(output.shape) 34 | # torch.Size([64, 3, 32, 32]) 35 | writer.add_images("input", imgs, step) 36 | # torch.Size([64, 6, 30, 30]) -> [xxx, 3, 30, 30] 37 | 38 | output = torch.reshape(output, (-1, 3, 30, 30)) 39 | writer.add_images("output", output, step) 40 | 41 | step = step + 1 42 | 43 | writer.close() 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | import torchvision 6 | from PIL import Image 7 | from torch import nn 8 | 9 | image_path = "../imgs/airplane.png" 10 | image = Image.open(image_path) 11 | print(image) 12 | image = image.convert('RGB') 13 | transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)), 14 | torchvision.transforms.ToTensor()]) 15 | 16 | image = transform(image) 17 | print(image.shape) 18 | 19 | class Tudui(nn.Module): 20 | def __init__(self): 21 | super(Tudui, self).__init__() 22 | self.model = nn.Sequential( 23 | nn.Conv2d(3, 32, 5, 1, 2), 24 | nn.MaxPool2d(2), 25 | nn.Conv2d(32, 32, 5, 1, 2), 26 | nn.MaxPool2d(2), 27 | nn.Conv2d(32, 64, 5, 1, 2), 28 | nn.MaxPool2d(2), 29 | nn.Flatten(), 30 | nn.Linear(64*4*4, 64), 31 | nn.Linear(64, 10) 32 | ) 33 | 34 | def forward(self, x): 35 | x = self.model(x) 36 | return x 37 | 38 | model = torch.load("tudui_29_gpu.pth", map_location=torch.device('cpu')) 39 | print(model) 40 | image = torch.reshape(image, (1, 3, 32, 32)) 41 | model.eval() 42 | with torch.no_grad(): 43 | output = model(image) 44 | print(output) 45 | 46 | print(output.argmax(1)) 47 | -------------------------------------------------------------------------------- /src/nn_optim.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | import torchvision 6 | from torch import nn 7 | from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear 8 | from torch.optim.lr_scheduler import StepLR 9 | from torch.utils.data import DataLoader 10 | 11 | dataset = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(), 12 | download=True) 13 | 14 | dataloader = DataLoader(dataset, batch_size=1) 15 | 16 | class Tudui(nn.Module): 17 | def __init__(self): 18 | super(Tudui, self).__init__() 19 | self.model1 = Sequential( 20 | Conv2d(3, 32, 5, padding=2), 21 | MaxPool2d(2), 22 | Conv2d(32, 32, 5, padding=2), 23 | MaxPool2d(2), 24 | Conv2d(32, 64, 5, padding=2), 25 | MaxPool2d(2), 26 | Flatten(), 27 | Linear(1024, 64), 28 | Linear(64, 10) 29 | ) 30 | 31 | def forward(self, x): 32 | x = self.model1(x) 33 | return x 34 | 35 | 36 | loss = nn.CrossEntropyLoss() 37 | tudui = Tudui() 38 | optim = torch.optim.SGD(tudui.parameters(), lr=0.01) 39 | for epoch in range(20): 40 | running_loss = 0.0 41 | for data in dataloader: 42 | imgs, targets = data 43 | outputs = tudui(imgs) 44 | result_loss = loss(outputs, targets) 45 | optim.zero_grad() 46 | result_loss.backward() 47 | optim.step() 48 | running_loss = running_loss + result_loss 49 | print(running_loss) 50 | -------------------------------------------------------------------------------- /src/P9_transforms.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import Dataset, DataLoader 2 | from PIL import Image 3 | import os 4 | from torchvision import transforms 5 | 6 | class MyData(Dataset): 7 | 8 | def __init__(self, root_dir, image_dir, label_dir, transform=None): 9 | self.root_dir = root_dir 10 | self.image_dir = image_dir 11 | self.label_dir = label_dir 12 | self.label_path = os.path.join(self.root_dir, self.label_dir) 13 | self.image_path = os.path.join(self.root_dir, self.image_dir) 14 | self.image_list = os.listdir(self.image_path) 15 | self.label_list = os.listdir(self.label_path) 16 | self.transform = transform 17 | # 因为label 和 Image文件名相同,进行一样的排序,可以保证取出的数据和label是一一对应的 18 | self.image_list.sort() 19 | self.label_list.sort() 20 | 21 | def __getitem__(self, idx): 22 | img_name = self.image_list[idx] 23 | label_name = self.label_list[idx] 24 | img_item_path = os.path.join(self.root_dir, self.image_dir, img_name) 25 | label_item_path = os.path.join(self.root_dir, self.label_dir, label_name) 26 | img = Image.open(img_item_path) 27 | with open(label_item_path, 'r') as f: 28 | label = f.readline() 29 | 30 | if self.transform: 31 | img = transform(img) 32 | 33 | 34 | return img, label 35 | 36 | def __len__(self): 37 | assert len(self.image_list) == len(self.label_list) 38 | return len(self.image_list) 39 | 40 | 41 | transform = transforms.Compose([transforms.Resize(400), transforms.ToTensor()]) 42 | root_dir = "dataset/train" 43 | image_ants = "ants_image" 44 | label_ants = "ants_label" 45 | ants_dataset = MyData(root_dir, image_ants, label_ants, transform=transform) 46 | image_bees = "bees_image" 47 | label_bees = "bees_label" 48 | bees_dataset = MyData(root_dir, image_bees, label_bees, transform=transform) 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/read_data.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import Dataset, DataLoader 2 | import numpy as np 3 | from PIL import Image 4 | import os 5 | from torchvision import transforms 6 | from torch.utils.tensorboard import SummaryWriter 7 | from torchvision.utils import make_grid 8 | 9 | writer = SummaryWriter("logs") 10 | 11 | class MyData(Dataset): 12 | 13 | def __init__(self, root_dir, image_dir, label_dir, transform): 14 | self.root_dir = root_dir 15 | self.image_dir = image_dir 16 | self.label_dir = label_dir 17 | self.label_path = os.path.join(self.root_dir, self.label_dir) 18 | self.image_path = os.path.join(self.root_dir, self.image_dir) 19 | self.image_list = os.listdir(self.image_path) 20 | self.label_list = os.listdir(self.label_path) 21 | self.transform = transform 22 | # 因为label 和 Image文件名相同,进行一样的排序,可以保证取出的数据和label是一一对应的 23 | self.image_list.sort() 24 | self.label_list.sort() 25 | 26 | def __getitem__(self, idx): 27 | img_name = self.image_list[idx] 28 | label_name = self.label_list[idx] 29 | img_item_path = os.path.join(self.root_dir, self.image_dir, img_name) 30 | label_item_path = os.path.join(self.root_dir, self.label_dir, label_name) 31 | img = Image.open(img_item_path) 32 | 33 | with open(label_item_path, 'r') as f: 34 | label = f.readline() 35 | 36 | # img = np.array(img) 37 | img = self.transform(img) 38 | sample = {'img': img, 'label': label} 39 | return sample 40 | 41 | def __len__(self): 42 | assert len(self.image_list) == len(self.label_list) 43 | return len(self.image_list) 44 | 45 | if __name__ == '__main__': 46 | transform = transforms.Compose([transforms.Resize((256, 256)), transforms.ToTensor()]) 47 | root_dir = "dataset/train" 48 | image_ants = "ants_image" 49 | label_ants = "ants_label" 50 | ants_dataset = MyData(root_dir, image_ants, label_ants, transform) 51 | image_bees = "bees_image" 52 | label_bees = "bees_label" 53 | bees_dataset = MyData(root_dir, image_bees, label_bees, transform) 54 | train_dataset = ants_dataset + bees_dataset 55 | 56 | # transforms = transforms.Compose([transforms.Resize(256, 256)]) 57 | dataloader = DataLoader(train_dataset, batch_size=1, num_workers=2) 58 | 59 | writer.add_image('error', train_dataset[119]['img']) 60 | writer.close() 61 | # for i, j in enumerate(dataloader): 62 | # # imgs, labels = j 63 | # print(type(j)) 64 | # print(i, j['img'].shape) 65 | # # writer.add_image("train_data_b2", make_grid(j['img']), i) 66 | # 67 | # writer.close() 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/train.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | 5 | import torchvision 6 | from torch.utils.tensorboard import SummaryWriter 7 | 8 | from model import * 9 | # 准备数据集 10 | from torch import nn 11 | from torch.utils.data import DataLoader 12 | 13 | train_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(), 14 | download=True) 15 | test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), 16 | download=True) 17 | 18 | # length 长度 19 | train_data_size = len(train_data) 20 | test_data_size = len(test_data) 21 | # 如果train_data_size=10, 训练数据集的长度为:10 22 | print("训练数据集的长度为:{}".format(train_data_size)) 23 | print("测试数据集的长度为:{}".format(test_data_size)) 24 | 25 | 26 | # 利用 DataLoader 来加载数据集 27 | train_dataloader = DataLoader(train_data, batch_size=64) 28 | test_dataloader = DataLoader(test_data, batch_size=64) 29 | 30 | # 创建网络模型 31 | tudui = Tudui() 32 | 33 | # 损失函数 34 | loss_fn = nn.CrossEntropyLoss() 35 | 36 | # 优化器 37 | # learning_rate = 0.01 38 | # 1e-2=1 x (10)^(-2) = 1 /100 = 0.01 39 | learning_rate = 1e-2 40 | optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate) 41 | 42 | # 设置训练网络的一些参数 43 | # 记录训练的次数 44 | total_train_step = 0 45 | # 记录测试的次数 46 | total_test_step = 0 47 | # 训练的轮数 48 | epoch = 10 49 | 50 | # 添加tensorboard 51 | writer = SummaryWriter("../logs_train") 52 | 53 | for i in range(epoch): 54 | print("-------第 {} 轮训练开始-------".format(i+1)) 55 | 56 | # 训练步骤开始 57 | tudui.train() 58 | for data in train_dataloader: 59 | imgs, targets = data 60 | outputs = tudui(imgs) 61 | loss = loss_fn(outputs, targets) 62 | 63 | # 优化器优化模型 64 | optimizer.zero_grad() 65 | loss.backward() 66 | optimizer.step() 67 | 68 | total_train_step = total_train_step + 1 69 | if total_train_step % 100 == 0: 70 | print("训练次数:{}, Loss: {}".format(total_train_step, loss.item())) 71 | writer.add_scalar("train_loss", loss.item(), total_train_step) 72 | 73 | # 测试步骤开始 74 | tudui.eval() 75 | total_test_loss = 0 76 | total_accuracy = 0 77 | with torch.no_grad(): 78 | for data in test_dataloader: 79 | imgs, targets = data 80 | outputs = tudui(imgs) 81 | loss = loss_fn(outputs, targets) 82 | total_test_loss = total_test_loss + loss.item() 83 | accuracy = (outputs.argmax(1) == targets).sum() 84 | total_accuracy = total_accuracy + accuracy 85 | 86 | print("整体测试集上的Loss: {}".format(total_test_loss)) 87 | print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size)) 88 | writer.add_scalar("test_loss", total_test_loss, total_test_step) 89 | writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step) 90 | total_test_step = total_test_step + 1 91 | 92 | torch.save(tudui, "tudui_{}.pth".format(i)) 93 | print("模型已保存") 94 | 95 | writer.close() 96 | -------------------------------------------------------------------------------- /src/train-cpu.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | 5 | import torchvision 6 | from torch.utils.tensorboard import SummaryWriter 7 | 8 | # 准备数据集 9 | from torch import nn 10 | from torch.utils.data import DataLoader 11 | 12 | train_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(), 13 | download=True) 14 | test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), 15 | download=True) 16 | 17 | # length 长度 18 | train_data_size = len(train_data) 19 | test_data_size = len(test_data) 20 | # 如果train_data_size=10, 训练数据集的长度为:10 21 | print("训练数据集的长度为:{}".format(train_data_size)) 22 | print("测试数据集的长度为:{}".format(test_data_size)) 23 | 24 | 25 | # 利用 DataLoader 来加载数据集 26 | train_dataloader = DataLoader(train_data, batch_size=64) 27 | test_dataloader = DataLoader(test_data, batch_size=64) 28 | 29 | # 创建网络模型 30 | class Tudui(nn.Module): 31 | def __init__(self): 32 | super(Tudui, self).__init__() 33 | self.model = nn.Sequential( 34 | nn.Conv2d(3, 32, 5, 1, 2), 35 | nn.MaxPool2d(2), 36 | nn.Conv2d(32, 32, 5, 1, 2), 37 | nn.MaxPool2d(2), 38 | nn.Conv2d(32, 64, 5, 1, 2), 39 | nn.MaxPool2d(2), 40 | nn.Flatten(), 41 | nn.Linear(64*4*4, 64), 42 | nn.Linear(64, 10) 43 | ) 44 | 45 | def forward(self, x): 46 | x = self.model(x) 47 | return x 48 | tudui = Tudui() 49 | 50 | # 损失函数 51 | loss_fn = nn.CrossEntropyLoss() 52 | 53 | # 优化器 54 | # learning_rate = 0.01 55 | # 1e-2=1 x (10)^(-2) = 1 /100 = 0.01 56 | learning_rate = 1e-2 57 | optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate) 58 | 59 | # 设置训练网络的一些参数 60 | # 记录训练的次数 61 | total_train_step = 0 62 | # 记录测试的次数 63 | total_test_step = 0 64 | # 训练的轮数 65 | epoch = 10 66 | 67 | # 添加tensorboard 68 | writer = SummaryWriter("../logs_train") 69 | 70 | for i in range(epoch): 71 | print("-------第 {} 轮训练开始-------".format(i+1)) 72 | 73 | # 训练步骤开始 74 | tudui.train() 75 | for data in train_dataloader: 76 | imgs, targets = data 77 | outputs = tudui(imgs) 78 | loss = loss_fn(outputs, targets) 79 | 80 | # 优化器优化模型 81 | optimizer.zero_grad() 82 | loss.backward() 83 | optimizer.step() 84 | 85 | total_train_step = total_train_step + 1 86 | if total_train_step % 100 == 0: 87 | print("训练次数:{}, Loss: {}".format(total_train_step, loss.item())) 88 | writer.add_scalar("train_loss", loss.item(), total_train_step) 89 | 90 | # 测试步骤开始 91 | tudui.eval() 92 | total_test_loss = 0 93 | total_accuracy = 0 94 | with torch.no_grad(): 95 | for data in test_dataloader: 96 | imgs, targets = data 97 | outputs = tudui(imgs) 98 | loss = loss_fn(outputs, targets) 99 | total_test_loss = total_test_loss + loss.item() 100 | accuracy = (outputs.argmax(1) == targets).sum() 101 | total_accuracy = total_accuracy + accuracy 102 | 103 | print("整体测试集上的Loss: {}".format(total_test_loss)) 104 | print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size)) 105 | writer.add_scalar("test_loss", total_test_loss, total_test_step) 106 | writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step) 107 | total_test_step = total_test_step + 1 108 | 109 | torch.save(tudui, "tudui_{}.pth".format(i)) 110 | print("模型已保存") 111 | 112 | writer.close() 113 | -------------------------------------------------------------------------------- /src/train_gpu_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | import torchvision 6 | from torch.utils.tensorboard import SummaryWriter 7 | 8 | # from model import * 9 | # 准备数据集 10 | from torch import nn 11 | from torch.utils.data import DataLoader 12 | 13 | # 定义训练的设备 14 | device = torch.device("cuda") 15 | 16 | train_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(), 17 | download=True) 18 | test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), 19 | download=True) 20 | 21 | # length 长度 22 | train_data_size = len(train_data) 23 | test_data_size = len(test_data) 24 | # 如果train_data_size=10, 训练数据集的长度为:10 25 | print("训练数据集的长度为:{}".format(train_data_size)) 26 | print("测试数据集的长度为:{}".format(test_data_size)) 27 | 28 | 29 | # 利用 DataLoader 来加载数据集 30 | train_dataloader = DataLoader(train_data, batch_size=64) 31 | test_dataloader = DataLoader(test_data, batch_size=64) 32 | 33 | # 创建网络模型 34 | class Tudui(nn.Module): 35 | def __init__(self): 36 | super(Tudui, self).__init__() 37 | self.model = nn.Sequential( 38 | nn.Conv2d(3, 32, 5, 1, 2), 39 | nn.MaxPool2d(2), 40 | nn.Conv2d(32, 32, 5, 1, 2), 41 | nn.MaxPool2d(2), 42 | nn.Conv2d(32, 64, 5, 1, 2), 43 | nn.MaxPool2d(2), 44 | nn.Flatten(), 45 | nn.Linear(64*4*4, 64), 46 | nn.Linear(64, 10) 47 | ) 48 | 49 | def forward(self, x): 50 | x = self.model(x) 51 | return x 52 | tudui = Tudui() 53 | tudui = tudui.to(device) 54 | 55 | # 损失函数 56 | loss_fn = nn.CrossEntropyLoss() 57 | loss_fn = loss_fn.to(device) 58 | # 优化器 59 | # learning_rate = 0.01 60 | # 1e-2=1 x (10)^(-2) = 1 /100 = 0.01 61 | learning_rate = 1e-2 62 | optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate) 63 | 64 | # 设置训练网络的一些参数 65 | # 记录训练的次数 66 | total_train_step = 0 67 | # 记录测试的次数 68 | total_test_step = 0 69 | # 训练的轮数 70 | epoch = 10 71 | 72 | # 添加tensorboard 73 | writer = SummaryWriter("../logs_train") 74 | 75 | for i in range(epoch): 76 | print("-------第 {} 轮训练开始-------".format(i+1)) 77 | 78 | # 训练步骤开始 79 | tudui.train() 80 | for data in train_dataloader: 81 | imgs, targets = data 82 | imgs = imgs.to(device) 83 | targets = targets.to(device) 84 | outputs = tudui(imgs) 85 | loss = loss_fn(outputs, targets) 86 | 87 | # 优化器优化模型 88 | optimizer.zero_grad() 89 | loss.backward() 90 | optimizer.step() 91 | 92 | total_train_step = total_train_step + 1 93 | if total_train_step % 100 == 0: 94 | print("训练次数:{}, Loss: {}".format(total_train_step, loss.item())) 95 | writer.add_scalar("train_loss", loss.item(), total_train_step) 96 | 97 | # 测试步骤开始 98 | tudui.eval() 99 | total_test_loss = 0 100 | total_accuracy = 0 101 | with torch.no_grad(): 102 | for data in test_dataloader: 103 | imgs, targets = data 104 | imgs = imgs.to(device) 105 | targets = targets.to(device) 106 | outputs = tudui(imgs) 107 | loss = loss_fn(outputs, targets) 108 | total_test_loss = total_test_loss + loss.item() 109 | accuracy = (outputs.argmax(1) == targets).sum() 110 | total_accuracy = total_accuracy + accuracy 111 | 112 | print("整体测试集上的Loss: {}".format(total_test_loss)) 113 | print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size)) 114 | writer.add_scalar("test_loss", total_test_loss, total_test_step) 115 | writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step) 116 | total_test_step = total_test_step + 1 117 | 118 | torch.save(tudui, "tudui_{}.pth".format(i)) 119 | print("模型已保存") 120 | 121 | writer.close() 122 | -------------------------------------------------------------------------------- /src/train_gpu_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 作者:小土堆 3 | # 公众号:我是土堆 4 | import torch 5 | import torchvision 6 | from torch.utils.tensorboard import SummaryWriter 7 | 8 | # from model import * 9 | # 准备数据集 10 | from torch import nn 11 | from torch.utils.data import DataLoader 12 | 13 | train_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(), 14 | download=True) 15 | test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), 16 | download=True) 17 | 18 | # length 长度 19 | train_data_size = len(train_data) 20 | test_data_size = len(test_data) 21 | # 如果train_data_size=10, 训练数据集的长度为:10 22 | print("训练数据集的长度为:{}".format(train_data_size)) 23 | print("测试数据集的长度为:{}".format(test_data_size)) 24 | 25 | 26 | # 利用 DataLoader 来加载数据集 27 | train_dataloader = DataLoader(train_data, batch_size=64) 28 | test_dataloader = DataLoader(test_data, batch_size=64) 29 | 30 | # 创建网络模型 31 | class Tudui(nn.Module): 32 | def __init__(self): 33 | super(Tudui, self).__init__() 34 | self.model = nn.Sequential( 35 | nn.Conv2d(3, 32, 5, 1, 2), 36 | nn.MaxPool2d(2), 37 | nn.Conv2d(32, 32, 5, 1, 2), 38 | nn.MaxPool2d(2), 39 | nn.Conv2d(32, 64, 5, 1, 2), 40 | nn.MaxPool2d(2), 41 | nn.Flatten(), 42 | nn.Linear(64*4*4, 64), 43 | nn.Linear(64, 10) 44 | ) 45 | 46 | def forward(self, x): 47 | x = self.model(x) 48 | return x 49 | tudui = Tudui() 50 | if torch.cuda.is_available(): 51 | tudui = tudui.cuda() 52 | 53 | # 损失函数 54 | loss_fn = nn.CrossEntropyLoss() 55 | if torch.cuda.is_available(): 56 | loss_fn = loss_fn.cuda() 57 | # 优化器 58 | # learning_rate = 0.01 59 | # 1e-2=1 x (10)^(-2) = 1 /100 = 0.01 60 | learning_rate = 1e-2 61 | optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate) 62 | 63 | # 设置训练网络的一些参数 64 | # 记录训练的次数 65 | total_train_step = 0 66 | # 记录测试的次数 67 | total_test_step = 0 68 | # 训练的轮数 69 | epoch = 10 70 | 71 | # 添加tensorboard 72 | writer = SummaryWriter("../logs_train") 73 | 74 | for i in range(epoch): 75 | print("-------第 {} 轮训练开始-------".format(i+1)) 76 | 77 | # 训练步骤开始 78 | tudui.train() 79 | for data in train_dataloader: 80 | imgs, targets = data 81 | if torch.cuda.is_available(): 82 | imgs = imgs.cuda() 83 | targets = targets.cuda() 84 | outputs = tudui(imgs) 85 | loss = loss_fn(outputs, targets) 86 | 87 | # 优化器优化模型 88 | optimizer.zero_grad() 89 | loss.backward() 90 | optimizer.step() 91 | 92 | total_train_step = total_train_step + 1 93 | if total_train_step % 100 == 0: 94 | print("训练次数:{}, Loss: {}".format(total_train_step, loss.item())) 95 | writer.add_scalar("train_loss", loss.item(), total_train_step) 96 | 97 | # 测试步骤开始 98 | tudui.eval() 99 | total_test_loss = 0 100 | total_accuracy = 0 101 | with torch.no_grad(): 102 | for data in test_dataloader: 103 | imgs, targets = data 104 | if torch.cuda.is_available(): 105 | imgs = imgs.cuda() 106 | targets = targets.cuda() 107 | outputs = tudui(imgs) 108 | loss = loss_fn(outputs, targets) 109 | total_test_loss = total_test_loss + loss.item() 110 | accuracy = (outputs.argmax(1) == targets).sum() 111 | total_accuracy = total_accuracy + accuracy 112 | 113 | print("整体测试集上的Loss: {}".format(total_test_loss)) 114 | print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size)) 115 | writer.add_scalar("test_loss", total_test_loss, total_test_step) 116 | writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step) 117 | total_test_step = total_test_step + 1 118 | 119 | torch.save(tudui, "tudui_{}.pth".format(i)) 120 | print("模型已保存") 121 | 122 | writer.close() 123 | --------------------------------------------------------------------------------