Pytorch快速入门笔记

小土堆Pytorch教程中记录一些实用的Pytorch相关操作.

加载数据

PIL

PIL类可以用于加载图像、保存图像等操作

1
2
from PIL import Image
img = Image.open('data/hymenoptera_data/train/ants/342438950_a3da61deab.jpg')

DataSet

DataSet是一个抽象类,需要实现其中的__getitem__方法,以及最好是实现__len__方法,不然不能用迭代器,用for循环的方式取数据,
以下是一个自定义数据集的设置方式,可以看到需要重写__getitem__方法取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyDataSet(Dataset):

def __init__(self, data_dir, transforms=None):
super().__init__()
self.data_dir = data_dir
self.image_paths = os.listdir(data_dir)
self.transforms = transforms

def __getitem__(self, index) -> T_co:
img_file_name = self.image_paths[index]
img = Image.open(self.data_dir + img_file_name)
img_trans = self.transforms(img)
return img_trans

def __len__(self):
return len(self.image_paths)

DataLoader

如果把DataSet看做一副牌,那么DataLoader就是用于定义如何发牌,或者对牌进行一些操作(洗牌、转换格式等),如果已经有一个数据集,那么可以通过这种方式定义data_loader

1
2
3
4
my_ds = MyDataSet(data_dir='data/hymenoptera_data/val/ants/', transforms=trans)
# drop_last: 总长度除bs 除不尽的时候是否去掉最后一个
# batch_size: 批的量
data_loader = DataLoader(dataset=my_ds, batch_size=2, shuffle=True, drop_last=True)

定义好的数据集,可以通过DataLoader加载,并通过for循环取数据,例如:

1
2
3
4
5
step = 0
for images in data_loader:
print(images.shape)
writer.add_images('image_batch', images, step) # (tag,Image,step(不添加这个参数 tensorboard里面的step始终为零))
step += 1

torchvision数据集的下载和使用

如果是一些成熟的数据集,比如CIFAR10,可以用封装好的方式获取数据集,这些数据集也是重写了DataSet类,可以传入transform

1
2
3
4
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)

Tensorboard 的使用

首先定义一个SummaryWriter(),然后就可以用writer里面的方法往tensorboard里面写数据,不仅可以添加过程量还可以添加单张图像。默认的路径保存到本地runs目录下,可以用SummaryWriter()

1
2
3
4
5
6
7
8
writer = SummaryWriter()
# 添加过程量(标量)
for n_iter in range(100):
writer.add_scalar('Loss/train', np.random.random(), n_iter)
writer.add_scalar('Loss/test', np.random.random(), n_iter)
writer.add_scalar('Accuracy/train', np.random.random(), n_iter)
writer.add_scalar('Accuracy/test', np.random.random(), n_iter)
writer.add_image(tag='test', img_tensor=img_tensor)

查看数据:cd到保存文件的文件夹下,输入tensorboard --logdir runs runs对应文件保存的目录,然后就可以通过访问http://localhost:6006/#timeseries查看记录的结果

Transforms 的使用

Transforms用来对一张图片进行一系列的转换,可以用Compose定义需要转换的内容

1
2
3
4
5
6
trans = transforms.Compose([
transforms.ToTensor(),
# transforms.RandomCrop(size=(50,50)) 随机裁剪
transforms.Resize((100, 100))
])

定义好转换之后,可以对单张图片进行转换,把图像传入就可以,例如:

1
2
3
4
5
6
7
8
# 添加图像
img = Image.open('data/hymenoptera_data/train/ants/342438950_a3da61deab.jpg')
# 图像转换
trans = transforms.Compose([
transforms.ToTensor(),
# transforms.RandomCrop(size=(50,50)) # 随机裁剪
])
img_tensor = trans(img)

常用函数

卷积函数

卷积函数的定义网上有很多了就不再赘述了,定义一个卷积核,然后和现在的矩阵进行卷积操作,可得到一个结果。

借用知乎2D卷积,nn.Conv2d和F.conv2d一段话:卷积操作:卷积核和扫过的小区域对应位置相乘再求和的操作,卷积完成后一般要加个偏置bias。一种Kernel如果分成多个通道上的子Kernel做卷积运算,最后运算结果还要加在一起后,再加偏置。

使用卷积运算的时候需要注意输入输出的尺寸,需要对齐,比如Conv2D 如果是函数就要求B ,C 两个维度要对齐。
需要注意的点是输入输出维度会根据stride、padding的设置改变,比如64×64的图像进去,不设置padding出来的图像可能就变成62×62了,如果还要保持图像尺寸一致(特别是复现论文的场景),需要反算一下stride和padding的值,这里公式在Pytorch Conv2d文档,需要的时候直接查阅就好。

关于可视化展示卷积函数中的stride、padding、dilation参数的含义,可参考文档:Convolution arithmetic

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

w = torch.rand(1, 3, 2, 2) # 对应 B C ×卷积核的 H W,前2个维度对应上(在H W两个维度上进行卷积)
res = F.conv2d(input=a, weight=w, stride=1)
print(res)

tensor([[[[-0.9163, -1.4657, -3.6013, ..., 0.1913, -1.4308, -1.1725],
[-1.7863, -1.1487, -3.5197, ..., -0.5010, -2.3962, -3.8177],
[-0.0863, -0.3723, -1.7177, ..., -1.9196, -1.4938, -2.6761],
...,
[ 0.8136, -4.5267, -0.6807, ..., -2.2519, 1.4239, -0.9793],
[ 1.8353, -1.8440, -3.9382, ..., -1.8193, 2.7279, 4.4726],
[ 0.5444, 1.2673, -3.4205, ..., -2.3179, -2.5870, -1.7544]]]])

池化函数

池化函数是深度学习中常用的技术,主要用于降低数据的维度和减少计算量。常见的池化函数包括:

  1. 最大池化(Max Pooling):在池化窗口内选取最大值作为输出,能够提取图像中的主要特征。
  2. 平均池化(Average Pooling):在池化窗口内取平均值作为输出,可以平滑输入数据,减少噪声的影响。
  3. 自适应池化(Adaptive Pooling):根据输入的大小自动调整池化窗口的大小,以适应不同的输入尺寸。

池化操作可以分为一维池化、二维池化和三维池化,具体取决于被池化的张量维数。池化不仅可以减小数据大小,还可以增加数据大小,具体取决于应用场景。

1
2
3
a = torch.randn(1, 3, 64, 64)
res = F.max_pool2d(a,kernel_size=2) # kernel_size指定2的话是默认2×2的2d(正方形)。而且池化默认区域不重叠的,默认步长就是kernel_size=2,这一点和卷积运算不一样
print(res.shape) # torch.Size([1, 3, 32, 32])

神经网络的搭建

卷积层、池化层、非线性激活层

通过引入torch.nn引入常见神经网络的层,包括卷积层、池化层等.以及非线性激活层,RELU SOFTMAX之类的,具体就不再展开了。

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
class MyNeuralNetwork(nn.Module):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.conv1 = nn.Conv2d(3, 64, 3, 1, 1)
self.conv2 = nn.Conv2d(3, 64, 3, 1, 0)
self.max_pool = nn.MaxPool2d(4)
self.relu = nn.ReLU()
self.softmax = nn.Softmax()
# in_channels: int,
# out_channels: int,
# kernel_size: _size_2_t,
# stride: _size_2_t = 1,
# padding: Union[str, _size_2_t] = 0,
# dilation: _size_2_t = 1,

a = torch.randn(1, 3, 64, 64)

mnn = MyNeuralNetwork()

res_conv1 = mnn.conv1(a)
print(res_conv1.shape) # torch.Size([1, 64, 64, 64])

res_conv2 = mnn.conv2(a)
print(res_conv2.shape) # torch.Size([1, 64, 62, 62])

res_max_pool = mnn.max_pool(a)
print(res_max_pool.shape) # torch.Size([1, 3, 16, 16])


线性层及其他层

未完待续

Sequential的使用


Pytorch快速入门笔记
https://runsstudio.github.io/2025/04/02/Pytorch快速上手/
发布于
2025年4月2日
许可协议