一些 pytorch 学习笔记
张量 Tensor
初始化
- 构造一个 5x3 矩阵,不初始化 (empty)
x = torch.empty(5,3)
print(x)
# 教程的输出
tensor(1.00000e-04 *
[[-0.0000, 0.0000, 1.5135],
[ 0.0000, 0.0000, 0.0000],
[ 0.0000, 0.0000, 0.0000],
[ 0.0000, 0.0000, 0.0000],
[ 0.0000, 0.0000, 0.0000]])
# 自己测试的输出
tensor([[9.6429e-39, 9.2755e-39, 9.1837e-39],
[9.3674e-39, 1.0745e-38, 1.0653e-38],
[9.5510e-39, 1.0561e-38, 1.0194e-38],
[1.1112e-38, 1.0561e-38, 9.9184e-39],
[1.0653e-38, 4.1327e-39, 1.0194e-38]])
- 构造一个随机初始化的矩阵 (rand)
x = torch.rand(5,3)
print(x)
# 输出
tensor([[ 0.6291, 0.2581, 0.6414],
[ 0.9739, 0.8243, 0.2276],
[ 0.4184, 0.1815, 0.5131],
[ 0.5533, 0.5440, 0.0718],
[ 0.2908, 0.1850, 0.5297]])
构造一个全为 0 的矩阵,且指定数据类型为 long (zeros)
ps. 如果想令填充数字为 1,则使用 torch.ones
x = torch.zeros(5,3,dtype=torch.long)
print(x)
# 输出
tensor([[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0]])
- 构建一个张量,直接使用数据(tensor)
x = torch.tensor([5.5, 3])
print(x)
# 输出
tensor([ 5.5000, 3.0000])
用正态分布的随机数创建张量
例如以下代码创建一个形状为(3, 4)的张量
其中每个元素都从均值为 0,标准差为 1 的标准正态分布中随机取样
torch.randn(3, 4) // 3,4是形状
# 输出
tensor([[ 0.4114, 0.3654, -0.3493, 0.2873],
[-0.1792, 1.5127, 1.5238, 1.1396],
[-0.2556, -0.2120, -0.1249, -0.4377]])
# 如果想产生可导的随机数
a = torch.randn(size=(),requires_grad=True)
- 基于已存在的 tensor 创建 tensor
# 返回一个与size大小相同的用1填充的张量。可选择改变数据类型
x = x.new_ones(5, 3, dtype=torch.double)
# 仅保留size
x = torch.randn_like(x, dtype=torch.float)
- 创建行向量(arange)
x = torch.arange(3)
# 输出
tensor([0, 1, 2])
- 获取维度信息(size)
x.size()
# 输出
torch.Size([5, 3])
- 访问元素形状和元素总数(shape & numel)
x.shape # torch.Size([12])
x.numel() # 12
- 访问张量长度(len)
len(x)
- 改变张量形状(reshape)
X = x.reshape(3, 4) # 变成3行4列
运算
加法
# + print(x+y) # torch.add() print(torch.add(x,y)) # 提供一个输出tensor作为参数 result = torch.empty(5, 3) torch.add(x, y, out=result) print(result) # in-place 直接在y上相加 y.add_(x) # 任何使张量发生变化的操作都有前缀"_"
减乘除方指
x-y # 减 x*y # 乘 x/y # 除 x**y # 方 torch.exp(x) # 指数
连接多个张量
x = [[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]] y = [[ 2., 1., 4., 3.], [ 1., 2., 3., 4.], [ 4., 3., 2., 1.]]
- 按行( dim=0 )
torch.cat((x,y),dim=0) # 输出 tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [ 2., 1., 4., 3.], [ 1., 2., 3., 4.], [ 4., 3., 2., 1.]])
- 按列( dim=1 )
torch.cat((x,y),dim=1) # 输出 tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.], [ 4., 5., 6., 7., 1., 2., 3., 4.], [ 8., 9., 10., 11., 4., 3., 2., 1.]])
通过逻辑运算符构建二元张量
X == Y # 输出 tensor([[False, True, False, True], [False, False, False, False], [False, False, False, False]])
对张量中所有元素求和
会产生只有一个元素的张量
x.sum() # 输出 tensor(66.)
指定在某维度上求和
不保留维度
eg. [2, 5, 4]
如果 axis=0,则把第 1 个去掉,也就是去掉 2,变成[5, 4]
如果 axis=1,则把第 2 个去掉,也就是去掉 5,变成[2, 4]
B = A.sum(axis=0)
保留维度( keepdims=True )
eg. [2, 5, 4]
如果 axis=0,则把第 1 个变成 1,也就是变成[1, 5, 4]
如果 axis=1,则把第 2 个变成 1,也就是变成[2, 1, 4]
B = A.sum(axis=0, keepdims=True)
在维度上累积求和( cumsum(axis=x) )
A = torch.arange(16).reshape(4,4).cumsum(axis=0) # 输出 在列上累积求和 tensor([[ 0, 1, 2, 3], [ 4, 6, 8, 10], [12, 15, 18, 21], [24, 28, 32, 36]])
求平均值
A.mean() A.sum()/A.numel() # 也可指定维度求和 A.mean(axis=0) A.sum(axis=0)/A.numel(axis=0)
形状不同的张量相加 - 广播机制
例如相加的是以下两个张量: tensor([[0], [1], [2]]), tensor([[0,1]]) 那么相加的时候,第一个会复制两列,第二个会复制三行 tensor([[0, 0], [1, 1], [2, 2]]) tensor([[0, 1], [0, 1], [0, 1]]) 然后再相加,变成 tensor([[0, 1], [1, 2], [2, 3]])
操作元素
索引
访问特定元素
x[0,1]
访问一行
x[1,:]
访问一列
x[:,1]
访问子区域
x[1:3,1:] # 取 1-2 行 x 1-3 列
每隔一定间隔选取元素
x[::3,::3] # 从0开始,每隔3行取该行元素,每隔2列取该列元素
选取最后一个元素(如果是二维数组,则选取最后一行)
x[-1]
修改
通过指定索引,将元素写入矩阵
x[1,2] = 9
为多个元素赋相同的值,只需要索引所有元素,然后为它们赋值
x[0:2,:] = 12
执行原地操作
执行一些操作可能会为新结果分配内存
如果想让变量在操作前后内存位置保持一致:
1. X += Y
2. X[:] = X + Y
转换为 NumPy 张量
A = X.numpy()
将大小为 1 的张量转换为 python 标量
a.item()
float(a)
int(a)
线性代数
标量
由只有一个元素的张量表示
x = torch.tensor([3.0])
创建 mxn 矩阵
A = torch.arange(20).reshape(5, 4)
// 输出
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
矩阵转置
A.T
点积
通过执行按元素乘法,再进行求和
torch.sum(x*y)
torch.dot(x, y)
只能应用于一维张量
torch.dot(x, y)
矩阵向量积 Ax
torch.mv(A, x)
矩阵乘法
torch.mm(A, B)
// 或
A*B
范数
L
2范数 || a ||矩阵元素平方和的平方根
torch.norm(u)
L
1范数矩阵元素绝对值之和
torch.abs(u).sum()