安装环境

参考视频
使用 Anaconda Navigator 换源(最简单)
因为学完了吴恩达机器学习,然后数学公式这边有点欠缺,打算看大部分西瓜书和统计学习方法后再学那个白板;pytorch也是在anaconda中安装环境,conda create -n pytorch python=3.6创建名为pytorch的环境,激活环境conda activate pytorch在进入环境安装pytorch,注意cuda版本是可以选的,用nvidia-smi查看当前显卡驱动的cuda版本也就是这个版本可以自定义,那么上次sleap出错会不会是cuda版本的问题,然后在pytorch官网选择合适的版本生成安装代码例如conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia

使用环境

pycharm可以选择anaconda中创建的环境

巧用dir,help,pyc终端

dir()打开,看见
help():说明书
dir(pytorch)
输出:1、2、3
dir(pytorch.3)
输出:
a.b,c
help(pytorch.3.a)
输出:
将此扳手放在特定地方,然后拧动
看到dir输出__a__说明具体到函数了
pyc终端中可以试验函数的具体数值如b=range(1,3)

pyc切换解释器

在编辑配置里添加python解释器选择对应的解释器,pyc里可以右键文件选择复制全局/相对路径,右下角也可以直接切换解释器

PyTorch加载数据初认识

Dataset:提供一种方式去获取数据及其label;如何获取每一个数据及其label;告诉我们总共有多少的数据
Dataloader:为后面的网络提供不同的数据形式
P6加载数据的类代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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(self.root_dir,self.label_dir)
self.img_path=os.listdir(self.path)
def __getitem__(self,idx):
img_name=self.img_path[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,labeld
def __len__(self):
return len(self.img_path)

对蚂蚁图像批量赋予标签代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
root_dir="练手数据集/train"
target_dir="ants_image"
img_path=os.listdir(os.path.join(root_dir,target_dir))
print(img_path)
# import pdb
#
# pdb.set_trace()
# 比如ants_label就是取前面的ants
label=target_dir.split('_')[0]
out_dir="ants_label"
for i in img_path:
file_name=i.split('.jpg')[0]
#输出至目录并写入label如ants
with open(os.path.join(root_dir,out_dir,"{}.txt".format(file_name)),'w')as f:
f.write(label)

如果报错把root_dir="练手数据集/train"改成root_dir=./"练手数据集/train"即可

P9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
# python的用法-》tensor数据类型
# 通过transforms.ToTensor:去看两个问测
#2、为什么我们需要Tensor数据类型
writer=SummaryWriter("./logs")
img_path="./练手数据集/train/ants_image/0013035.jpg"
img=Image.open(img_path)
#1、transforms该如何使用(python)
# 调用库中的类工具
tensor_trans=transforms.ToTensor()
# 类的实例化然后传值?
tensor_img=tensor_trans(img)
print(tensor_img)
writer.add_image("Tensor_img",tensor_img)
writer.close()

P10

pycharm终端无法显示环境,调用log得手动打代码

1
2
conda activate pytorch
tensorboard --logdir=logs

常见的Transforms

*输入 *PiL *Image.open()
*输出 *tensor *ToTensor()
*作用 *narrays *cv.imread()

类中__call__的用法

使用call可以直接给实例赋值调用。不需要子函数,说白了就是c++的运算符重载?

pyc查看结构

ctrl+左键进入模块py目录,左侧查看模块结构和函数,ctrl+P查看属性提示
tensor后的图片tensor_img[2][1][0],第一个2似乎表示通道,第二,3个表征像素位置,从0开始计数
writer.add_image("Tensor_imgN",img_norm,2)最后一个参数可调整步长,滑动查看之前的log

RandomCrop 随机裁剪但也能指定参数

指定参数的作用是随机裁剪的大小,必须小于原图
compose就相当于前面的两步转为一步,图片操作的组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
# python的用法-》tensor数据类型
# 通过transforms.ToTensor:去看两个问测
#2、为什么我们需要Tensor数据类型
writer=SummaryWriter("./logs")
img_path="./练手数据集/train/ants_image/0013035.jpg"
img=Image.open(img_path)
"""
ToTensor()
的使用
"""
#1、transforms该如何使用(python)
# 调用库中的类工具
tensor_trans=transforms.ToTensor()
# 类的实例化然后传值?
tensor_img=tensor_trans(img)
print(tensor_img)
writer.add_image("Tensor_img",tensor_img)
# writer.close()
# 归一化
"""
output[channel] =
(input[channel] - mean[channel]) / std[channel]
两个长度为三的数组,
分别表示三个通道的平均值和标准差
"""
# 第一个0似乎表示通道,第二,3个表征像素位置,从0开始计数

print(tensor_img[2][1][0])
trans_norm=transforms.Normalize([0.5,1,0.5],[1,0.5,0.5])
img_norm=trans_norm(tensor_img)
print(img_norm[2][1][0])
writer.add_image("Tensor_imgN",img_norm,2)
# Resize
print(img.size)
trans_resize=transforms.Resize((512,512))
#img PIL ->resize ->img_resize PIL
img_resize=trans_resize(img)
#img_resize PIL ->totensor ->img_resize tensor
img_resize=tensor_trans(img_resize)
writer.add_image("Resize",img_resize,0)
#Compose resize 2
trans_resize_2=transforms.Resize(512)
# compose就相当于前面的两步转为一步
trans_compose=transforms.Compose([trans_resize_2,tensor_trans])
img_resize_2=trans_compose(img)
writer.add_image("Resize",img_resize_2,1)
# RandomCrop 随机裁剪但也能指定参数
trans_random=transforms.RandomCrop(51)
trans_compose_2=transforms.Compose([trans_random,tensor_trans])
for i in range(10):
img_crop=trans_compose_2(img)
writer.add_image("Randomcrop",img_crop,i)

writer.close()

P15

batch_size的作用是在test_data中取若干个数据

P16 神经网络的基本骨架-nn.Module的使用

1
2
3
def forward(self,x):
x=F.relu(self.conv1(x))
return F.relu(self.conv2(x))

以上代码进行了如下操作:
1输入:X
2卷积
3非线性
4卷积
5非线性
6输出
在pyc中Windows ctrl+o可以重写方法

P16

torch.tensor和torch.Tensor也有区别哦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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四参数 经查证红字有误 第一个参数是batch size样本数量 第二个参数是channel图像的通道数量
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)

P18

Out_channel=3相当于三个卷积核卷积后叠加输出的数组,其形式相当于RGB三通道
代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.nn import Conv2d
from torch.utils.tensorboard import SummaryWriter

dataset=torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
"""
BATCH_SIZE的含义
BATCH_SIZE:即一次训练所抓取的数据样本数量;
BATCH_SIZE的大小影响训练速度和模型优化。同时按照以上代码可知,其大小同样影响每一epoch训练模型次数。
"""
dataloader=DataLoader(dataset,batch_size=64)
class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__init__()
self.conv1=Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)
#forward写卷积逻辑跟函数
def forward(self,x):
x=self.conv1(x)
return x

step=0
tudui1=Tudui()
writer=SummaryWriter("dataloader")
print(tudui1)
for data in dataloader:
imgs,targets=data
output=tudui1(imgs)
print(imgs.shape)
print(output.shape)
writer.add_images("input",imgs,step)
output=torch.reshape(output,(-1,3,30,30))

writer.add_images("output",output,step)
step=step+1

P19

池化层的步长默认是卷积核的大小,最大池化,就是取其中的最大值
ceil 允许有出界部分;floor 不允许
池化和卷积不一样的
矩阵版代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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)
# 原来是个二维的现在成四维的了
input=torch.reshape(input,(-1,1,5,5))
print(input.shape)

class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__init__()
self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=False)

def forward(self,input):
output=self.maxpool1(input)
return output
tudui=Tudui()
output=tudui(input)
print(output)

数据集版代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,batch_size=64)


class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__init__()
self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=False)

def forward(self,input):
output=self.maxpool1(input)
return output
tudui=Tudui()
writer=SummaryWriter("dataloadermaxpoolc")
step=0
for data in dataloader:
imgs, targets=data
writer.add_images("input", imgs, step)
output=tudui(imgs)
writer.add_images("output", output, step)
step=step+1
writer.close()

数据集版导入数据集后处理后的照片像是加了一层马赛克

P20

nn_relu.py
矩阵版代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import torch
import torchvision
from torch import nn
from torch.nn import ReLU
from torch.utils.tensorboard import SummaryWriter

input=torch.tensor([[1,-0.5],
[-1,3]])
output=torch.reshape(input,(-1,1,2,2))



class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__init__()
self.relu1=ReLU()
def forward(self,input):
output=self.relu1(input)
return output

tudui=Tudui()
output=tudui(input)
print(output)

P21

报错是因为数据集batch之后剩了16张图片,dataloader的参数drop_last设为true就不报错了,torch.flatten()用于把数据展平比如把二维展平成一维

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader


dataset=torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset, batch_size=64, drop_last=True)

class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__init__()
self.linear1=Linear(196608,10)
def forward(self,input):
output=self.linear1(input)
return output


tudui=Tudui()

for data in dataloader:
imgs, targets=data
print(imgs.shape)
# 变换维度以传入神经网络
output=torch.reshape(imgs,(1,1,1,-1))

output=torch.flatten(imgs)
print(output.shape)
output=tudui(output)
print(output.shape)

P22

CIFAR10代表有十个类别,torch.ones
这个是不太推荐的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear


class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__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)


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)
return x
tudui=Tudui()
print(tudui)
input=torch.ones((64,3,32,32))
output=tudui(input)
print(output.shape)

网络整合的版本

P23

所以是反向传播来计算梯度,根据梯度来更新参数,实现loss最小化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import torch
from torch import nn
from torch.nn import L1Loss
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(reduction='sum')
result=loss(inputs,targets)
loss_mse=nn.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)

P24

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset=torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset, batch_size=1)
class Tudui(nn.Module):
def __init__(self):
super(Tudui,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
tudui=Tudui()
for data in dataloader:
imgs,targets=data
outputs=tudui(imgs)
print(outputs)
print(targets)
loss=nn.CrossEntropyLoss()
result_loss=loss(outputs, targets)
print(result_loss)
result_loss.backward()
print("ok")

P25

优化问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset=torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset, batch_size=1)
class Tudui(nn.Module):
def __init__(self):
super(Tudui,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
tudui=Tudui()
optim=torch.optim.SGD(tudui.parameters(),lr=0.01)
for epoch in range(20):
running_loss=0.0
for data in dataloader:
imgs,targets=data
outputs=tudui(imgs)
loss=nn.CrossEntropyLoss()
result_loss=loss(outputs, targets)
#梯度清理防止保留上次的梯度迭代
optim.zero_grad()
result_loss.backward()
optim.step()
running_loss=running_loss+result_loss
print(running_loss)

P26

pretrained=True就是会加载网络默认的参数参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

import torchvision
from torch import nn

# train_data=torchvision.datasets.ImageNet("../data_image_net",split="train",download=True,transform=torchvision.transforms.ToTensor())
vgg16_true=torchvision.models.vgg16(pretrained=True)
vgg16_false=torchvision.models.vgg16(pretrained=False)
print(vgg16_true)

train_data=torchvision.datasets.CIFAR10("../data",train=True,transform=torchvision.transforms.ToTensor(),download=True)
# 对vgg16_true的classifier层增加一层线性层
vgg16_true.classifier.add_module("add_linear",nn.Linear(1000,10))
print(vgg16_true)
# vgg16的[6]层进行修改,线性层修改为4096,10
print(vgg16_false)
vgg16_false.classifier[6]=nn.Linear(4096,10)
print(vgg16_false)

P27

保存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

import torchvision
import torch
from torch import nn

vgg16=torchvision.models.vgg16(pretrained=False)
# 保存方式1保存网络结构+模型参数
torch.save(vgg16,"vgg16_method1.pth")
#加载模型方式1
model=torch.load("vgg16_method1.pth")
print(model)
# 保存方式2,模型参数(官方推荐空间小)
torch.save(vgg16.state_dict(),"vgg16_method2.pth")
#加载模型参数
model=torch.load("vgg16_method2.pth")
print(model)
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")
#这句话如果要在别的py文件里加载是要复制Class类或者import Tudui
model1=torch.load("tudui_method1.pth")
print(model1)

CNN中stride(步幅)和padding(填充)的详细理解
图像卷积后像素大小没变

P28

item()可以把tensor中的数值取出来,应该说0是指定第0轴[竖着看],1指定第1轴[横着看]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

from model import Tudui

# 添加tensorboard
writer=SummaryWriter("logs_train")
# 准备数据集
train_data=torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),
download=True)
test_data=torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),
download=True)
# length 长度
train_data_size=len(train_data)
test_data_size=len(test_data)
# 如果train_data_size代表训练数据集的长度
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)
#创建网络模型
tudui=Tudui()
#损失函数
loss_fn=nn.CrossEntropyLoss()
#优化器
learning_rate=1e-2
optimizer=torch.optim.SGD(tudui.parameters(),lr=learning_rate)
# 设置训练网络的一些参数
total_train_step=0
# 训练的轮数
epoch=10
total_test_step=0
for i in range(epoch):
print("第{}轮训练开始".format(i+1))
# 训练步骤开始
for data in train_dataloader:
imgs,targets=data
outputs=tudui(imgs)
loss=loss_fn(outputs,targets)
# 优化器模型cc
optimizer.zero_grad()
loss.backward()
optimizer.step()

total_train_step=total_train_step+1
if total_train_step % 10==0:
print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
writer.add_scalar("train_loss",loss.item(),total_train_step)
# 测试步骤开始
total_test_loss=0
total_accuracy=0
# with torch.no_grad():的意思是测试过程中不用对模型进行调优直接用现有的模型就行
with torch.no_grad():
for data in test_dataloader:
imgs,targets=data
outputs=tudui(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))
total_test_step = total_test_step+1
writer.add_scalar("test_loss", loss.item(), total_test_step)
writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
torch.save(tudui,"tudui_{}.pth".format(i))
print("模型已保存")

writer.close()

GPU训练

第一种训练方式新增以下代码

1
2
3
4
5
6
7
if torch.cuda.is_available():
tudui=tudui.cuda()
if torch.cuda.is_available():
loss_fn=loss_fn.cuda()
if torch.cuda.is_available():
imgs=imgs.cuda()
targets=targets.cuda()

start_time=time.time()
end_time = time.time()
这两句话可以看情况加
tudui.train()
tudui.eval()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
import time
from model import Tudui

# 添加tensorboard
writer=SummaryWriter("logs_train")
start_time=time.time()
# 准备数据集
train_data=torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),
download=True)
test_data=torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),
download=True)
# length 长度
train_data_size=len(train_data)
test_data_size=len(test_data)
# 如果train_data_size代表训练数据集的长度
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)
#创建网络模型
tudui=Tudui()
if torch.cuda.is_available():
tudui=tudui.cuda()

#损失函数
loss_fn=nn.CrossEntropyLoss()
if torch.cuda.is_available():
loss_fn=loss_fn.cuda()
#优化器
learning_rate=1e-2
optimizer=torch.optim.SGD(tudui.parameters(),lr=learning_rate)

# 设置训练网络的一些参数
total_train_step=0
# 训练的轮数
epoch=10
total_test_step=0
for i in range(epoch):
print("第{}轮训练开始".format(i+1))
# 训练步骤开始
tudui.train()
for data in train_dataloader:
imgs,targets=data
if torch.cuda.is_available():
imgs=imgs.cuda()
targets=targets.cuda()
outputs=tudui(imgs)
loss=loss_fn(outputs,targets)
# 优化器模型cc
optimizer.zero_grad()
loss.backward()
optimizer.step()

total_train_step=total_train_step+1
if total_train_step % 100==0:
end_time = time.time()
print(end_time - start_time)
print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
writer.add_scalar("train_loss",loss.item(),total_train_step)
# 测试步骤开始
tudui.eval()
total_test_loss=0
total_accuracy=0
# with torch.no_grad():的意思是测试过程中不用对模型进行调优直接用现有的模型就行
with torch.no_grad():
for data in test_dataloader:
imgs,targets=data
if torch.cuda.is_available():
imgs = imgs.cuda()
targets = targets.cuda()
outputs=tudui(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))
total_test_step = total_test_step+1
writer.add_scalar("test_loss", loss.item(), total_test_step)
writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
torch.save(tudui,"tudui_{}.pth".format(i))
print("模型已保存")
writer.close()

第二种训练方式主要使用语句device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
在第9行要加image=image.convert('RGB')
因为png格式是四个通道,除了RGB三通道外,还有一个透明度通道。
所以,我们调用image=image.convert(RGB),保留其颜色通道
当然,如果图片本来就是三个颜色通道,经过此操作,不变。
加上这一步后,可以适应png,jpg各种格式的图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import torch
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
import time
from model import Tudui


#定义训练设备
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
# device=torch.device("cuda")
# device=torch.device("cpu")

# 添加tensorboard
writer=SummaryWriter("logs_train")
start_time=time.time()
# 准备数据集
train_data=torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),
download=True)
test_data=torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),
download=True)
# length 长度
train_data_size=len(train_data)
test_data_size=len(test_data)
# 如果train_data_size代表训练数据集的长度
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)
#创建网络模型
tudui=Tudui()
tudui=tudui.to(device)

#损失函数
loss_fn=nn.CrossEntropyLoss()
#这个不另外赋值
loss_fn=loss_fn.to(device)
#优化器
learning_rate=1e-2
optimizer=torch.optim.SGD(tudui.parameters(),lr=learning_rate)

# 设置训练网络的一些参数
total_train_step=0
# 训练的轮数
epoch=10
total_test_step=0
for i in range(epoch):
print("第{}轮训练开始".format(i+1))
# 训练步骤开始
tudui.train()
for data in train_dataloader:
imgs,targets=data
imgs=imgs.to(device)
targets=targets.to(device)
outputs=tudui(imgs)
loss=loss_fn(outputs,targets)
# 优化器模型cc
optimizer.zero_grad()
loss.backward()
optimizer.step()

total_train_step=total_train_step+1
if total_train_step % 100==0:
end_time = time.time()
print(end_time - start_time)
print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
writer.add_scalar("train_loss",loss.item(),total_train_step)
# 测试步骤开始
tudui.eval()
total_test_loss=0
total_accuracy=0
# with torch.no_grad():的意思是测试过程中不用对模型进行调优直接用现有的模型就行
with torch.no_grad():
for data in test_dataloader:
imgs,targets=data
if torch.cuda.is_available():
imgs = imgs.cuda()
targets = targets.cuda()
outputs=tudui(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))
total_test_step = total_test_step+1
writer.add_scalar("test_loss", loss.item(), total_test_step)
writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
torch.save(tudui,"tudui_{}.pth".format(i))
print("模型已保存")
model=torch.load("tudui_0.pth")
writer.close()

输入/输出类型都应该为cuda,如果出现常见错误: RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor),则添加:

1
2
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")  
image=image.to(device)

如果模型参数使用gpu训练的而本机环境只有CPU则用语句map_location=torch.device('cpu')转换