pytorch学习——初探

我并没有系统地翻阅Pytorch文档,一般都是看别人pytorch实现的网络代码,哪里有不懂的再去看.现在找到一些tutorial并做一些简单的尝试.

整体流程

image-20230914101921453

image-20230912094601559

首先定义网络架构,注意这里也有很多要点,比如像写代码一样,使用模块嵌套,最终形成一个个小模块组成的大模块,模块的超参设置也很重要.

1
2
3
4
import torch
model = torch.nn.Linear(1, 1)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr = 0.1)

损失函数需要根据任务去确定,常用交叉熵.优化器基本没有太多改进空间了,常用的Adam或者RMSprop.在训练时,通过梯度更新参数,再进行验证,通过这样来判断是否过拟合等等.

image-20230912095110476

以上是关于网络的训练,对于一般的任务,对于数据集的处理也是非常重要的,导入之前需要做一些transforms,不同任务做的变化不一样,比如图像的话,一般数据集是PIL数据,需要将其转为Tensor类型数据,还可能需要normalize等等.

1
2
3
4
5
6
7
import torch
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.datasets import MNIST

dataset = MNIST(root='./data', train=True, download=True, transform=transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=100, shuffle=True)

数据处理

上面用的Dataset都是自带的,很多时候需要用我们自己的数据集,那么需要重写Dataset

1
2
3
4
5
6
7
8
9
10
11
12
from torch.utils.data import Dataset

class MyDataset(Dataset):
def __init__(self, data, file):
# read data and preprocess
pass
def __getitem__(self,index):
# return one sample at a time
pass
def __len__(self):
# return the size of the dataset
pass

然后使用dataloader方便读入batch以及shuffle打乱

1
2
dataset = MyDataset(data, './data/train.csv')
dataloader = DataLoader(dataset, batch_size=100, shuffle=True)

Pytorch中的dim与numpy中的axis一样的,有的时候类似这种术语经常出现混乱.

常用操作

transpose 互换维度

squeezz 去掉指定的长度为1的维度

unsqueezz 增加一个长度唯一的维度

cat 将给定维度中的seq张量的给定序列连接起来。所有张量必须具有相同的形状(连接维度除外)或为空

stack 沿着一个新的维度连接一系列张量。 所有张量的大小都必须相同。

tensor数据类型

Data typedtypeCPU tensorGPU tensor
32-bit floating pointtorch.float32 or torch.floattorch.FloatTensortorch.cuda.FloatTensor
64-bit floating pointtorch.float64 or torch.doubletorch.DoubleTensortorch.cuda.DoubleTensor
32-bit integer (signed)torch.int32 or torch.inttorch.IntTensortorch.cuda.IntTensor

pytorch中的tensor与numpy都有shape和dtype属性

在方法上,pytorch用于变更维度的有reshape和view(很多时候看别人代码里用view不要忘了其作用).此外numpy也有squeezz,但是没有unsqueezz,而是使用expand_dims

而torch.Tensor与np.ndarray比较大的差别是tensor可以在GPU上跑,同时也可以设置梯度.

1
torch.cuda.is_available() # 查看GPU是否可用

通过torch.tensor创造tensor时,会根据输入设置dtype,如果输入是int,那就是int32或者int64,跟os有关,如果是浮点数就是float32.如果使用torch.ones这种来创建tensor,dtype默认是float32.

torch.nn定义模型

nn.Linear

image-20230914094934618

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import torch 
import torch.nn as nn
import torch.nn.functional as F

class MyModel(nn.Module):
def __init__(self):
super(). __init__()
self.net = nn.Sequential(
nn.Linear(10,32),
nn.Sigmoid(),
nn.Linear(32,1)
)
def forward(self, x):
x = self.net(x)

对于每一个batch,首先需要使用optimizer.zero_grad()去除gradient,然后使用loss.backward()通过损失函数计算梯度,最后使用optimizer.step更新梯度.

标准训练流程如下

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 torch.nn as nn

class MyModel(nn.Module):
def __init__(self):
super(). __init__()
self.net = nn.Sequential( # 也可以使用nn.Linear nn.Sigmoid连续写
nn.Linear(10,32),
nn.Sigmoid(),
nn.Linear(32,1)
)
def forward(self, x):
x = self.net(x)

criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model = MyModel().to(DEVICE)

for epoch in range(n_epochs):
model.train()
for x,y in tr_set:
optimizer.zero_grad()
x,y = x.to(DEVICE),y.to(DEVICE)
pred = model(x)
loss = criterion(pred,y)
loss.backward()
optimizer.step()
model.eval()

验证时,

1
2
3
4
5
6
7
8
9
model.eval()
total_loss = 0
for x,y in te_set:
x,y = x.to(DEVICE),y.to(DEVICE)
with torch.no_grad():
pred = model(x)
loss = criterion(pred,y)
total_loss += loss.cpu().item()
print(f'Epoch {epoch}: loss = {total_loss}')

注意 计算出的loss除了在计算backward时,其他地方需要放在cpu上并移除梯度,应该注意这些细节,也就是将原本在cuda上的数据放在cpu上,并且将tensor数据转为python的数据类型.

Pytorch训练过程中,显存(内存)爆炸解决方法 - 知乎 (zhihu.com)

1
2
3
4
5
6
7
model.eval()
preds = []
for x in tt_test:
x = x.to(device)
with torch.no_grad():
pred = model(x)
preds.append(pred.cpu())

image-20230914224438072

在训练验证时需要使用model.eval与model.train切换模型中每层的行为,在测试时防止将测试数据放入模型中计算.

此外要多翻阅Pytorch文档.

参考资料

  1. 【機器學習 2023】 PyTorch Tutorial (introduction + documentation) - YouTube
  2. torch.Tensor — PyTorch 2.0 documentation
  3. wkentaro/pytorch-for-numpy-users: PyTorch for Numpy users. https://pytorch-for-numpy-users.wkentaro.com (github.com)
-------------本文结束感谢您的阅读-------------
感谢阅读.

欢迎关注我的其它发布渠道