跳至内容
PyTorch_note

PyTorch_note

https://docs.pytorch.org/docs/stable/torch.html

PyTorch

一些 API

1
import torch
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# tensor creation
torch.tensor([2,3.]) # 将...转为tensor
torch.randn((2,3)) # 2*3维0-1随机值张量,标准正态分布 N(0, 1)
torch.zeros(*size, dtype=None, requires_grad=False) → Tensor
torch.ones(*size, dtype=None, requires_grad=False) → Tensor
torch.zeros_like()
torch.ones_like()
torch.arange(start=0, end, step=1, dtype=None, requires_grad=False) → Tensor
torch.arange(0,6,2) # tensor([0, 2, 4])
torch.linespace(0,10,5) # tensor([ 0.0000,  2.5000,  5.0000,  7.5000, 10.0000])
torch.eye(n, m=None, requires_grad=False) → Tensor # (3)等价于(3,3) (3,2)或(3,5)都是主对角线为1
torch.full(size, fill_value, dtype=None, requires_grad=False) → Tensor # 将某值填充到指定size的tensor
1
2
3
4
5
# torch.is_xxx
torch.is_tensor()
torch.is_complex()
torch.is_floating_point()
torch.is_nonzero()
1
2
3
4
5
6
# torch.numel
torch.numel()
a = torch.randn(1, 2, 3, 4, 5)
torch.numel(a) # 120

a.shape # torch.Size([1, 2, 3, 4, 5])
1
2
3
4
5
6
7
# torch.set_default_tensor_type
a = torch.tensor([1,2.])
print(a.dtype) # torch.float32

torch.set_default_tensor_type(torch.DoubleTensor)
b=torch.tensor([3.,4])
b.dtype # torch.float64
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# operations_1
torch.cat(tensors, dim=0) → Tensor # 除了连接维度外,其他维度要完全相同
torch.chunk(Tensor, chunks: int, dim: int = 0) → Tuple[Tensor] # 从某维上尽可能均匀分割,最后一个较短
torch.gather(Tensor, dim, index: Tensor) → Tensor # 根据某维的索引取得一个新张量,具体看下一代码块
torch.scatter(Tensor, dim, index, src) → Tensor # 和.gather对比看下一代码块
torch.scatter_add(Tensor, dim, index, src) → Tensor # scatter_add_的 Out-of-place version
torch.reshape(Tensor, shape) → Tensor # 维度乘积相等,遵循由高维到低维顺序
Tensor.scatter_(dim, index, src) # _结尾的是某变量的原地修改方法
Tensor.scatter_add_(dim, index, src)
torch.split(Tensor, split_size_or_sections: int/List[int], dim=0) → Tensor # 类似chunk的划分
torch.squeeze(Tensor, dim: int/List[int]) → Tensor # 把长度为1的维度去掉,可以指定哪些维度
torch.stack(tensors, dim=0) → Tensor # 指定维度堆叠,与torch.cat不同,torch.cat沿着存在的维度进行拼接
 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
# torch.gather
# index的维度数一致,index内的“一层元素”的维度除 = Input除指定维度外的维度,看下面的c就知道
import torch
a = torch.arange(24).reshape(2,3,4)
b = torch.gather(a, dim=2, index = 
	torch.tensor([
		[[3,2,3,2],[2,2,2,2],[1,1,1,1]],
		[[3,2,3,2],[2,2,2,2],[1,1,1,1]]
		])
	)
c =	torch.gather(a, dim=2, index = 
	torch.tensor([[[3,2,3,2],
				[2,2,2,2],
				[1,1,1,1]]])
	)
a, b, c

----------------------------------------
tensor([[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
         [ 8,  9, 10, 11]],

        [[12, 13, 14, 15],
         [16, 17, 18, 19],
         [20, 21, 22, 23]]])
tensor([[[ 3,  2,  3,  2],
         [ 6,  6,  6,  6],
         [ 9,  9,  9,  9]],

        [[15, 14, 15, 14],
         [18, 18, 18, 18],
         [21, 21, 21, 21]]])
tensor([[[3, 2, 3, 2],
         [6, 6, 6, 6],
         [9, 9, 9, 9]]])

-------
gather
    数据流向:大矩阵 → 小(或同)张量
    作用:按索引 把值挑出来 组成新结果。
    特点:不需要事先准备“容器”,返回的就是新 Tensor。
scatter_
    数据流向:小(或同)张量 → 大矩阵
    作用:按索引 把值写进去(会累冲或覆盖)。
    特点:必须提前有一个 目标张量(通常全 0),且形状可以 更大;写完后目标内容被修改。

 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
# torch.reshape:在不改变数据总量和顺序的前提下,改变张量的形状(维度)。
x = torch.arange(12)  # [0, 1, ..., 11], 形状 [12]

# 变成 3行4列
a = x.reshape(3, 4)
# 结果: [[0,1,2,3], [4,5,6,7], [8,9,10,11]]

# 我只要 3行,列数你帮我算 (12/3 = 4)
b = x.reshape(3, -1)  # 形状变为 [3, 4]

# 我只要 2列,行数你帮我算 (12/2 = 6)
c = x.reshape(-1, 2)  # 形状变为 [6, 2]

# 广播机制必备 `-1` (自动推导某维长度),一次 reshape 中**只能出现一个 `-1`**。
y = torch.arange(3)   # [0, 1, 2]

# 变成列向量 (竖着排) -> [N, 1]
col = y.reshape(-1, 1) 
# 结果: [[0], [1], [2]]

# 变成行向量 (横着排) -> [1, N]
row = y.reshape(1, -1)
# 结果: [[0, 1, 2]]

# Flatten
# 假设 f 是个 [2, 2, 3] 的三维张量
f = torch.zeros(2, 2, 3)

# 压缩成一维向量
flat = f.reshape(-1)
# 结果形状: [12]
1
2
3
4
5
6
7
8
# operation2
torch.take(Tensor, index) → Tensor # 将输入视为一维张量 取出一个张量
torch.tile(Tensor, dims) → Tensor # 贴瓷砖式复制
torch.transpose(Tensor, dim0, dim1) → Tensor # 对dim0和dim1进行转置
torch.unbind(Tensor, dim=0) → tuple[Tensor] # 把张量 沿指定维度“拆开”,返回拆开后的张量的元组。
torch.unsqueeze(Tensor, dim: int) → Tensor # 在指定位置 插入一个长度为 1 的新维度,接近.squeeze的逆操作
torch.where(condition, input: Tensor, other) → Tensor # input if condition else other,是否保留input
torch.manual_seed(seed)
1
2
3
4
5
# random sampling
torch.manual_seed(seed: int) # 为生成随机值手动设定种子
torch.bernoulli(input: Tensor) → Tensor # 伯努利分布,输入各个位置是概率,输出0/1
torch.normal(mean, std) → Tensor # 正态分布 经典用法:torch.normal(2, 3, size=(1, 4))
torch.randperm(n, dtype=torch.int64) → Tensor# 打乱 0 到 n-1 整数,生成一个不重复随机排列(permutation)。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 切片赋值
"""
左值[切片] = 右值,左侧切片会创建一个指向原内存的“视图” ,右侧数据必须与该视图形状完全一致(或可广播)。
"""

# 基础步长赋值 vec 形状 [6],source 形状 [3] -> 填入索引 0, 2, 4
vec[0::2] = source 

# 多维特定列填充 mat 形状 [H, W], sub_mat 形状 [H, W/2] -> 填入第 0, 2, 4... 列
mat[:, 0::2] = sub_mat

# 区域广播填充 mat 形状 [H, W] -> 将所有奇数列置为 0
mat[:, 1::2] = 0

# Transformer 位置嵌入
pos_emb_table[:,0::2] = torch.sin(pos_mat/i_mat)
pos_emb_table[:,1::2] = torch.cos(pos_mat/i_mat)
"""
左侧pos_emb_table 原本是 [20, 8] 切片视图 [:, 0::2],形状变为 [20, 4],右侧 torch.sin(...),形状也是 [20, 4]。
"""

Datasets & DataLoaders

Datasets & DataLoaders

Dataset:将磁盘数据转为 “一行行的” x-y pairs (单个样本),自定义的需要至少自定义 __init__, __len__, and __getitem__,可能需要对特征、标签进行预处理。

DataLoader: 将Dataset转为可以用于训练的 mini-batch,并具有shuffle、sampler、collate_fn的功能或自定义函数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 自定义Dataset(CustomImageDataset)例子
import os
import pandas as pd
from torchvision.io import decode_image

class CustomImageDataset(Dataset):
    def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
        self.img_labels = pd.read_csv(annotations_file)
        self.img_dir = img_dir
        self.transform = transform
        self.target_transform = target_transform

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

    def __getitem__(self, idx):
        img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
        image = decode_image(img_path)
        label = self.img_labels.iloc[idx, 1]
        if self.transform:
            image = self.transform(image)
        if self.target_transform:
            label = self.target_transform(label)
        return image, label

DataLoader

class torch.utils.data.DataLoader

  • dataset (Dataset) – dataset from which to load the data.

  • batch_size (int, optional) – how many samples per batch to load (default: 1).

  • shuffle (bool, optional) – set to True to have the data reshuffled at every epoch (default: False).

  • sampler (Sampler or Iterable, optional) – 采样者,与shuffle互斥.

  • batch_sampler (Sampler or Iterable, optional) – 批次采样者,如果传入了,则不可传入batch_size, shuffle, sampler, and drop_last.

  • num_workers (int, optional) – 线程数. (default: 0)

  • collate_fn (Callable, optional) – sample后的操作,也就是对batch的后处理.

  • drop_last (bool, optional) – 是否丢弃最后那个不完整的batch(除去刚好完整的情况). (default: False)

  • generator (torch.Generator, optional) – If not None, this RNG will be used by RandomSampler to generate random indexes and multiprocessing to generate base_seed for workers. (default: None)

Transforms

Transforms — PyTorch Tutorials 2.9.0+cu128 documentation

可以在前面的CustomImageDataset中看到 transform 和 target_transform 的 应用

transform:对特征

target_transform:对标签

nn.Module

Module — PyTorch 2.9 documentation

一个__init__, 一个forward。

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


class Model(nn.Module):
    def __init__(self) -> None:
        super().__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

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

net.apply(),net是nn.Module实例,作用为应用 参数处理函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
@torch.no_grad()
def init_weights(m):
    print(m)
    if type(m) == nn.Linear:
        m.weight.fill_(1.0)
        print(m.weight)
net = nn.Sequential(nn.Linear(2, 2), nn.Linear(2, 2))
net.apply(init_weights)

# Linear(in_features=2, out_features=2, bias=True)
# Parameter containing:
# tensor([[1., 1.],
#         [1., 1.]], requires_grad=True)
# Linear(in_features=2, out_features=2, bias=True)
# Parameter containing:
# tensor([[1., 1.],
#         [1., 1.]], requires_grad=True)
# Sequential(
#   (0): Linear(in_features=2, out_features=2, bias=True)
#   (1): Linear(in_features=2, out_features=2, bias=True)
# )
最后更新于