最近做实验发现自己还是基础框架上掌握得不好,于是开始重学一遍PyTorch框架,这个是课程笔记,这个课还是讲的简略,我半小时的课听了一个半小时。
1. PyTorch的数据类型
数据类型 | dtype参数 | 遗留的构造函数 |
---|---|---|
32位浮点数 | torch.float32 或 torch.float | torch.*.FloatTensor |
64位浮点数 | torch.float64 或 torch.double | torch.*.DoubleTensor |
64位复数 | torch.complex64 或 torch.cfloat | |
182位复数 | torch.complex128 或 torch.cdouble | |
第一类16位浮点数 | torch.float16 或 torch.half (指数位是用5个比特表示的) | torch.*.HalfTensor |
第二类16位浮点数 | torch.bfloat16( 指数位是用8个比特表示的) | torch.*.BFloat16Tensor |
8位无符号整数 | torch.uint8 | torch.*.ByteTensor |
8位有符号整数 | torch.int8 | torch.*.CharTensor |
16位有符号整数 | torch.int16 或 torch.short | torch.*.ShortTensor |
32位有符号整数 | torch.int32 或 torch.int | torch.*.IntTensor |
64位有符号整数 | torch.int64 或 torch.long | torch.*.LongTensor |
布尔类型 | torch.bool | torch.*.BoolTensor |
浮点数计算方式详见IEEE 754二进制浮点数算术标准百度百科,实际炼丹的时候注意一下就行,不用细究,主要是精度不同。
2. 张量操作
(1)take:返回一个新张量,其元素为给定索引处的输入。输入张量被视为1-D张量。结果与索引具有相同的形状。
python
import torch
src = torch.tensor([[4, 3, 5],
[6, 7, 8]])
a = torch.take(src, torch.tensor([0, 2, 5])) # 无论src是几维张量,都将其按行优先变成1维张量
#take[4, 3, 5, 6, 7, 8]从中找到下标位0, 2, 5的元素
print(a)
运行结果:
tensor([4, 5, 8])
(2)tile:通过重复输入的元素来构造张量。dims是指定在哪一个维度进行重复。如果 dims 指定的维度少于输入的维度,则将 ones 添加到 dims 之前,直到指定了所有维度。例如,如果输入的形状为 (8, 6, 4, 2),而 dims 为 (2, 2),则将 dims 视为 (1, 1, 2, 2)。
python
import torch
x = torch.tensor([1, 2, 3])
print(x.tile((2,))) # 相当于对[1, 2, 3]复制两份
y = torch.tensor([[1, 2], [3, 4]])
# 对第一个维度行复制两份,对第二个维度列复制两份
print(torch.tile(y, (2, 2)))
# 先复制行[[1,2], [3,4], [1,2], [3,4]]
# 再复制列[[1,2,1,2], [3,4,3,4], [1,2,1,2], [3,4,3,4]]
print(torch.tile(y, (3, 2))) # 第一个维度复制3份,第二个维度复制两份
# 先复制行[[1,2], [3,4], [1,2], [3,4], [1,2], [3,4]]
# 再复制列[[1,2,1,2], [3,4,3,4], [1,2,1,2], [3,4,3,4], [1,2,1,2], [3,4,3,4]]
运行结果:
tensor([1, 2, 3, 1, 2, 3])
tensor([[1, 2, 1, 2],
[3, 4, 3, 4],
[1, 2, 1, 2],
[3, 4, 3, 4]])
tensor([[1, 2, 1, 2],
[3, 4, 3, 4],
[1, 2, 1, 2],
[3, 4, 3, 4],
[1, 2, 1, 2],
[3, 4, 3, 4]])
(3)transpose:对张量进行转置(二维张量,也就是矩阵,它的转置就类似矩阵转置),如果是多维度,可以通过dim0和dim1确定交换维度。
python
import torch
x = torch.randn(2, 3)
print(x)
x = torch.transpose(x, 0, 1) # 交换维度0和维度1,相当于取转置,写1, 0也是一样的,都是交换(转置)
print(x)
运行结果:
tensor([[-1.9731, -0.1187, 1.4879],
[ 0.7525, -1.9673, -0.9391]])
tensor([[-1.9731, 0.7525],
[-0.1187, -1.9673],
[ 1.4879, -0.9391]])
(4)unbind:移除一个张量的维度,默认移除0维度。
python
import torch
# 默认按维度0(行)消除张量的维度,即拆分
print(torch.unbind(torch.tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])))
# 按维度1(列)消除张量的维度,即拆分
print(torch.unbind(torch.tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]), dim = 1))
运行结果:
(tensor([1, 2, 3]), tensor([4, 5, 6]), tensor([7, 8, 9]))
(tensor([1, 4, 7]), tensor([2, 5, 8]), tensor([3, 6, 9]))
(5)unsqueeze:在某些特定的维度上新增一个维度。
python
import torch
# 在x维度上新增一维度,x的范围是(-x.dim-1,x.dim+1)
x = torch.tensor([1, 2, 3, 4])
a = torch.unsqueeze(x, 0) # 在第0维度新增一个维度(新增后的第0维(行),是行上新增一个维度)
print(a)
b = torch.unsqueeze(x, 1) # 在第1维度新增一个维度(新增后的第1维(列),是列上新增一个维度)
print(b)
c = torch.unsqueeze(x, -1) # 在第最后一个维度新增一个维度(新增后的最后一个维度就是第1维(列),是列上新增一个维度)
print(c)
运行结果:
tensor([[1, 2, 3, 4]])
tensor([[1],
[2],
[3],
[4]])
tensor([[1],
[2],
[3],
[4]])
(6)vsplit:根据indices _or_sections,将输入(一个具有二维或多维的张量)垂直拆分为多个张量。每个分割都是一个输入视图。
python
import torch
t = torch.arange(16.0).reshape(4,4)
print(t)
a = torch.vsplit(t, 2) # 按垂直方向(行)分两份
print(a)
b = torch.vsplit(t, [3, 6]) # 按垂直方向(行)分3:6粉
print(b)
运行结果:
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.]])
(tensor([[0., 1., 2., 3.],
[4., 5., 6., 7.]]), tensor([[ 8., 9., 10., 11.],
[12., 13., 14., 15.]]))
(tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]]), tensor([[12., 13., 14., 15.]]), tensor([], size=(0, 4)))
(7)vstack:垂直(逐行)按顺序堆叠张量。
python
import torch
a = torch.tensor([1, 2, 3]) # 行向量
b = torch.tensor([4, 5, 6]) # 行向量
print(torch.vstack((a,b))) # 按垂直(行)方向,拼接行向量
a = torch.tensor([[1],[2],[3]]) # 列向量
b = torch.tensor([[4],[5],[6]]) # 列向量
print(torch.vstack((a,b))) # 按垂直(行)方向,拼接列向量
运行结果:
tensor([[1, 2, 3],
[4, 5, 6]])
tensor([[1],
[2],
[3],
[4],
[5],
[6]])
(8)where:根据条件,返回从输入或其他输入中选择的元素的张量。(类似if else条件)
python
import torch
x = torch.randn(3, 2) # 随机值3x2张量
y = torch.ones(3, 2) # 全1的3X2张量
print(x)
print(torch.where(x > 0, 1.0, 0.0)) # x某个位置元素大于0就将这个位置的元素赋值为1,否则就将这个位置的元素赋值为0
print(torch.where(x > 0, x, y)) # x某个位置元素大于0就保留,否则就将这个位置的元素赋值为y对应位置的元素
x = torch.randn(2, 2, dtype=torch.double)
print(x)
print(torch.where(x > 0, x, 0.)) # x某个位置元素大于0就将这个位置的元素赋值为x原本对应位置的元素,否则就将这个位置的元素赋值为0
运行结果:
tensor([[ 1.2857, 0.6624],
[-1.2176, -0.2741],
[-0.7331, -0.6283]])
tensor([[1., 1.],
[0., 0.],
[0., 0.]])
tensor([[1.2857, 0.6624],
[1.0000, 1.0000],
[1.0000, 1.0000]])
tensor([[ 0.0079, -0.1124],
[ 0.6240, -0.1965]], dtype=torch.float64)
tensor([[0.0079, 0.0000],
[0.6240, 0.0000]], dtype=torch.float64)
(9)manual_seed :设置用于生成随机数的种子。固定随机种子,方便对论文的复现。参数随机初始化,初始值不一样结果不同,如果随机种子固定就不会变化。
(10)bernoulli:伯努利采样,基于伯努利概率模型生成采样值,返回的是0或者1.
python
import torch
a = torch.empty(3, 3).uniform_(0, 1) # 生成服从正态分布的3x3矩阵
print(a)
print(torch.bernoulli(a))
a = torch.ones(3, 3) # 3X3全为1的张量(概率为1)
print(torch.bernoulli(a))
a = torch.zeros(3, 3) # 3X3全为0的张量(概率为0)
print(torch.bernoulli(a))
运行结果:
tensor([[0.5975, 0.4570, 0.8206],
[0.4460, 0.0134, 0.4570],
[0.2273, 0.1717, 0.5898]])
tensor([[1., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]])
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
【GPT回答】伯努利分布是概率论和统计学中的一种离散型概率分布,用来描述只有两种可能结果的随机试验,比如成功或失败、正面或反面、1或0等。它以其名字命名于瑞士数学家雅各布·伯努利。在伯努利分布中,随机变量取值为1表示成功的概率,取值为0表示失败的概率。这个分布的参数是成功的概率 p p p,通常表示为 Bern ( p ) \text{Bern}(p) Bern(p)。伯努利分布的概率质量函数可以用以下公式表示:
P ( X = x ) = p x ⋅ ( 1 − p ) 1 − x P(X=x) = p^x \cdot (1-p)^{1-x} P(X=x)=px⋅(1−p)1−x其中, x x x 可以取 0 或 1,分别对应失败和成功, p p p 是成功的概率。
伯努利分布的期望值 E ( X ) E(X) E(X) 可以用 p p p 表示,方差 Var ( X ) ) 则为 ( p ( 1 − p ) \text{Var}(X) ) 则为 ( p(1-p) Var(X))则为(p(1−p)。这个分布在许多领域中都有广泛的应用,比如在金融领域的二项期权定价、医学试验的结果分析、工程项目的成功率分析等。
(11)normal:生成正态分布的采样,传入的参数是均值和方差。可以单独传均值和标准差,也可以共享均值,标准差传入的是一个张量。也可以共享标准差,均值不同。
python
import torch
print(torch.normal(mean=torch.arange(1., 11.), std=torch.arange(1, 0, -0.1))) # 均值是1到11,方差是1到0,步长是-0.1
# 共享均值0.5,标准差不一样
print(torch.normal(mean=0.5, std=torch.arange(1., 6.)))
# 均值不一样,共享标准差
print(torch.normal(mean=torch.arange(1., 6.)))
# 从均值为2,标准差为3的正态分布中取样出2X4的张量
print(torch.normal(2, 3, size=(2, 4)))
运行结果:
tensor([0.6761, 2.1100, 2.9759, 4.0812, 4.8908, 5.5873, 7.5505, 7.2527, 8.9929,
9.9476])
tensor([ 1.5508, 0.2023, 0.2276, -0.1333, 2.6893])
tensor([1.2311, 1.9547, 2.9189, 4.6270, 4.2430])
tensor([[-1.5097, -3.3287, 2.7755, 0.3581],
[ 5.4610, 2.5765, 2.7561, 3.8923]])
(12)rand:从0到1的区间(左闭右开)生成均匀分布。
python
import torch
print(torch.rand(4)) # 一维长度为4的[0,1)的均匀分布
print(torch.rand(2, 3)) # 二维2X3的[0,1)的均匀分布
运行结果:
tensor([0.0835, 0.1057, 0.9253, 0.3540])
tensor([[0.9528, 0.7700, 0.2160],
[0.8131, 0.7256, 0.2035]])
(13)randint:从指定区间随机取整数。左闭右开。
python
import torch
print(torch.randint(3, 5, (3,))) # 在[3, 5)的整数中随机取三个值
运行结果:
tensor([4, 3, 4])
(14)randn:从均值为0标准差为1的正态分布中采样随机浮点数。
python
import torch
print(torch.randn(4)) # 生成长度为1的1维的均值为0标准差为1的正态分布的随机采样浮点数值
print(torch.randn(2, 3)) # 生成2X3的2维的均值为0标准差为1的正态分布的随机采样浮点数值
运行结果:
tensor([ 0.0714, -2.0626, -1.5583, 1.6608])
tensor([[ 1.0924, -1.8781, -0.1767],
[-0.7686, 1.1433, 1.4133]])
(15)randperm:将[0, x)中的整数进行随机组合。构建数据集,随机化数据集经常用。
python
import torch
print(torch.randperm(4)) # 生成[0,4)的整数的随机组合
运行结果:
tensor([1, 2, 3, 0])