文章目录
- 创建
- empty、zeros、ones
- `new_*` : new_ones
- rand / randn / randperm / randint / randn_like
- normal
- uniform_
- eye
- 创建列表,类似 numpy 中的 arange
- 创建等差数列 linspace
- logspace 返回一维张量
- 稠密向量
- Tensor -- Numpy
- 属性和方法
- 数据类型转换
- 判断一个对象是否为 Tensor
- 判断一个对象是否为 PyTorch Storage 类型
- item
- 获取 Tensor 中元素个数 numel
- 尺寸 shape / size
- 修改形状 view
- 转置
- 将输入张量分割成相同形状的 chunks
- 增加矩阵维度 unsqueeze
- 降低纬度(去掉 []) squeeze
- 获取沿着某个维度切片后 所有的切片 unbind
- 拼接 cat
- 按指定维度切分 chunk
- 聚合 gather
- 改变尺寸
- 索引、切片
- 高级选择函数
- 按照索引选择目标数据 index_select
- 选出满足条件的矩阵元素 masked_select
- 找出矩阵中的非零元素的索引 nonzero
- 数学计算
- 加法
- 乘法
- 绝对值、向上取整、向下取整、相反数、倒数、平方根、平方根倒数
- 每个元素加减乘除
- 指、对、幂
- 三角函数
- 线性插值
- Sigmoid 函数,sign符号函数
- 规约计算
- 累积 & 累和
- 均值、中位数、众数、方差、标准差
- p-norm 距离
- 数值比较运算
- 大于、小于、等于、不等于
- 最大值、最小值 max、min
- 排序 sort
- topk
- 矩阵运算
- 对角矩阵
- 矩阵的迹
- 上三角矩阵和下三角矩阵
- 矩阵的乘积 mm
- 特征值及特征向量
- 广播机制
- 其它
- 设置打印选项
- 全局设置 Tensor 数据类型
- 随机抽样
- 设置随机种子
- 伯努利分布采样
- 多项式分布抽样
- 标准分布抽样
- 在 gpu/cpu 运行
详见官方文档
https://pytorch.org/docs/stable/tensors.html
创建
可以参考借鉴 numpy
-
Tensor(*sizes)
, 基础构造函数,指定形状 -
Tensor(data)
, 使用数据直接初始化,类似np.array的构造函数
-
*_like
创建与已知tensor 形状相同的 tensor。如zeros_like
,ones_like
。 -
new_*
创建与已知tensor 类型相同的 tensor
定义一个序列
empty(*sizes)
-
ones(*sizes)
, 全 1 Tensor,单位矩阵 -
zeros(*sizes)
, 全 0 Tensor -
eye(*sizes)
, 对角线为1,其他为0
-
arange(s,e,step)
, 从s到e,步长为step -
linspace(s,e,steps)
, 从s到e,均匀切分成steps份 -
rand/randn(*sizes)
, 均匀分布/标准正态分布 -
normal(mean,std) / uniform(from,to)
, 正态分布/均匀分布 -
randperm(m)
, 随机排列
import torch
# 创建二两三列的数据
t1 = torch.Tensor(2,3)
# tensor([[1.0000, 1.0000, 1.0000], [1.0000, 1.0000, 1.0000]])
# 根据数组创建
t1 = torch.Tensor([2,3])
# tensor([2., 3.])
t1 = torch.tensor([5.5, 3])
# tensor([5.5000, 3.0000])
t1 = torch.Tensor([[2,3], [1, 4]])
# tensor([[2., 3.], [1., 4.]])
torch.Tensor & torch.tensor
- torch.Tensor是主要的tensor类,所有的tensor都是torch.Tensor的实例。
- 全局默认数据类型是 torch.float32
- torch.Tensor是torch.FloatTensor的别名。
- torch.Tensor 传入数字代表形状;
- torch.Tensor 传入可迭代对象,表示数据。类型为模型的数据类型。
- torch.tensor 为创建 tensor 的方法。
- torch.tensor是一个函数,返回的是一个tensor
empty、zeros、ones
# 创建空数组;但内容不为空,有填充。
t1 = torch.empty(2, 3)
# tensor([[ 0.0000e+00, -2.5244e-29, 0.0000e+00], [-2.5244e-29, 1.6816e-44, 0.0000e+00]])
t1 = torch.zeros(2, 3, dtype=torch.long)
# tensor([[0, 0, 0], [0, 0, 0]])
t1 = torch.ones([2, 3]) # 等价于 torch.ones(2, 3)
# tensor([[1., 1., 1.], [1., 1., 1.]])
# 相同size,全部元素为 0
t2 = torch.zeros_like(t1)
# tensor([[0., 0.], [0., 0.]])
new_*
: new_ones
创建与已知tensor 类型相同的 tensor
# new_* 得到数据类型相同的 tensor
tensor = torch.tensor((), dtype=torch.int32)
tensor.new_ones((2, 3))
# tensor([[1, 1, 1],
# [1, 1, 1]], dtype=torch.int32)
tensor = torch.tensor((), dtype=torch.float64)
tensor.new_ones((2, 3))
# tensor([[1., 1., 1.],
# [1., 1., 1.]], dtype=torch.float64)
rand / randn / randperm / randint / randn_like
# 生成 2*3 的随机张量,服从 [0, 1) 标准正态分布
t1 = torch.rand(2, 3) # 等价于 torch.rand([2, 3])
# tensor([[0.9694, 0.3158, 0.6500], [0.0295, 0.8634, 0.6159]])
torch.randn(2, 3)
# tensor([[ 0.8246, 0.7402, 1.5977], [-0.6260, 0.6390, -0.9222]])
# 创建两行三列的随机整数 tensor,随机值区间是 [low, high)
# torch 中一般使用 size 获取尺寸,而非 numpy 中的shape
torch.randint(low=1, high=10, size=[2, 3])
# tensor([[8, 9, 4], [8, 4, 5]])
# 值在 [0, 8) 以内,尺寸为 [3, 5]
t1 = torch.randint(8, [3, 5])
# tensor([[1, 7, 7, 6, 7], [3, 1, 2, 1, 1], [4, 0, 5, 5, 2]])
np.random.permutation(10)
# array([1, 8, 2, 6, 5, 9, 3, 7, 4, 0])
torch.randperm(10)
# tensor([1, 9, 6, 3, 7, 2, 4, 5, 0, 8])
# 利用 randn_like 方法得到 相同张量尺寸 的一个新张量, 并且采用随机初始化来对其赋值
t1 = torch.randn_like(t1, dtype=torch.float)
# tensor([[ 0.2930, 1.1197, 1.8780], [-1.1264, -1.2930, -0.1120]])
# 指定新的数据类型
t1 = torch.randn_like(t1, dtype=torch.float)
# tensor([[-0.5377, 0.9886, -1.2924], [ 0.1119, -0.4485, 0.9149]])
normal
normal(mean, std, *, generator=None, out=None)
该函数返回从单独的正态分布中提取的随机数的张量,该正态分布的均值是mean,标准差是std。
# 从一个标准正态分布N~(0,1),提取一个2x2的矩阵
torch.normal(mean=100.,std=1.,size=(2,2))
# tensor([[ 99.8296, 99.3379], [101.4170, 100.2711]])
# 生成平均值为0,标准差为随机的5个张量
t1 = torch.normal(mean=0.0, std=torch.rand(5))
# tensor([ 0.0401, 0.3874, -0.0811, 0.0051, 0.4429])
# 五组随机的面,五个随机的标准差;得到五组不同的正态分布
t1 = torch.normal(mean=torch.rand(5), std=torch.rand(5))
# tensor([ 1.0911, -0.8740, 0.1921, 0.9249, 0.1547])
uniform_
t1 = torch.Tensor(2, 2)
# tensor([[2.3694e-38, nan], [2.8026e-45, 0.0000e+00]])
t1.uniform_(-1, 1)
# tensor([[-0.2414, -0.2573], [-0.5572, 0.4906]])
eye
torch.eye(3, 3)
'''
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
'''
torch.eye(3, 4)
'''
tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])
'''
创建列表,类似 numpy 中的 arange
np.arange(1, 10, 3)
# array([1, 4, 7])
torch.arange(1, 10, 3)
# tensor([1, 4, 7])
创建等差数列 linspace
# start / end / step
# step : 个数
torch.linspace(1, 9, 3, requires_grad=True)
# tensor([1., 5., 9.], requires_grad=True)
logspace 返回一维张量
和 linspace 相似。包含在区间 和 中。
以对数刻度均匀间隔的 steps 个点,输出一维张量的长度为 steps。
torch.logspace(1, 5, 5, requires_grad=True)
# tensor([1.00000e+01, 1.00000e+02, 1.00000e+03, 1.00000e+04, 1.00000e+05], requires_grad=True)
稠密向量
# 将对角线定义为非零元素
i = torch.tensor([[0, 1, 2], [0, 1, 2]])
v = torch.tensor([1, 2, 3])
t1 = torch.sparse_coo_tensor(i, v, [5, 4])
'''
tensor(indices=tensor([[0, 1, 2],
[0, 1, 2]]),
values=tensor([1, 2, 3]),
size=(5, 4), nnz=3, layout=torch.sparse_coo)
'''
# 转化为稠密张量
t2 = t1.to_dense()
'''
tensor([[1, 0, 0, 0],
[0, 2, 0, 0],
[0, 0, 3, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
'''
Tensor – Numpy
Torch Tensor 和 Numpy array 之间的相互转换
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
# array([[1, 2, 3], [4, 5, 6]])
t1 = torch.tensor(arr)
# tensor([[1, 2, 3], [4, 5, 6]])
# 方式2,效果同上
a2 = torch.from_numpy(arr) # tensor([[1, 2, 3], [4, 5, 6]])
# numpy 数组的改变,不会影响 tensor
np.add(arr, 1, out=arr)
t2 = t1.numpy() # array([[1, 2, 3], [4, 5, 6]])
t1.add_(1) # tensor([[2, 3, 4], [5, 6, 7]])
t2 # b同时被改变, 但 arr 不会被改变
# array([[2, 3, 4], [5, 6, 7]])
属性和方法
数据类型转换
torch 支持的类型:
t1 = torch.Tensor([1., 2.])
t1.dtype # torch.float32
# 创建时制定数据类型
t2 = torch.ones([2, 3], dtype=torch.float32)
# tensor([[1., 1., 1.], [1., 1., 1.]])
# 强制转换
t2.double() # .int(), .long(),
# tensor([[1., 1., 1.], [1., 1., 1.]], dtype=torch.float64)
t3 = torch.LongTensor([2, 3])
# tensor([2, 3])
t3.dtype # torch.int64
使用 Tensor 创建,不支持 dtype, tensor 支持
在 jupyter 中可以使用 help(torch.tensor)
查看帮助文档
参数值太小,会导致梯度消失。
数值太大,会梯度爆炸。
判断一个对象是否为 Tensor
obj = np.arange(1, 10)
torch.is_tensor(obj) # False
t1 = torch.Tensor(10)
torch.is_tensor(t1) # True
判断一个对象是否为 PyTorch Storage 类型
s1 = torch.DoubleStorage(5)
s1
'''
0.0
0.0
0.0
0.0
0.0
[torch.DoubleStorage of size 5]
'''
torch.is_storage(s1) # True
item
当张量中只有一个值,可以使用 item 获取那个值。
t1 = torch.Tensor([[[1]]]) # tensor([[[1.]]])
a.item() # 1.0
# 张量内有两个值时,会报错
t2 = torch.Tensor([[[1, 2]]])
b.item() # only one element tensors can be converted to Python scalars
获取 Tensor 中元素个数 numel
t1 = torch.Tensor(3, 4)
torch.numel(t1)
12
尺寸 shape / size
- shape 属性
- size() 方法,比较常用。可以指定维度。
- dim(), 获取维数
t1 = torch.tensor([[[1, 2, 3], [4, 5, 6]]])
a.shape # torch.Size([1, 2, 3])
a.size() # torch.Size([1, 2, 3])
a.size(0) # 1 # 第0维的尺寸
a.size(1) # 2
a.size(-1) # 3 最后一维的长度
a.dim() # 3
修改形状 view
numpy 中使用 reshape,这里也可以用,但不推荐。建议使用 view。
两者都是浅拷贝,仅仅改变形状
t1 = torch.tensor([[[1, 2, 3], [4, 5, 6]]])
t2 = t1.view([3, 2])
# tensor([[1, 2], [3, 4], [5, 6]])
t3 = t1.view([-1])
# tensor([1, 2, 3, 4, 5, 6])
# t1 修改后,t2和 c 中的数值也会修改
a.add_(1)
转置
Numpy 中使用 T,torch 中使用 t。
二维可以使用 t 转置,高维使用 transpose。
t1 = torch.tensor([[1, 2], [3, 4]])
# tensor([[1, 2],
# [3, 4]])
t1.t()
# tensor([[1, 3],
# [2, 4]])
# 效果同上,且此时 t1 中数据不变
t1.transpose(0, 1)
# 多维
t1 = torch.tensor([[[1, 2, 3],[4, 5, 6]],
[[7, 8, 9],[10, 11, 12]]])
t2 = torch.transpose(t1, 1, 2)
# 效果同上
t3 = t1.transpose(1, 2)
'''
tensor([[[ 1, 4],
[ 2, 5],
[ 3, 6]],
[[ 7, 10],
[ 8, 11],
[ 9, 12]]]),
'''
将输入张量分割成相同形状的 chunks
非 truck
t1 = torch.ones(2, 10)
'''
tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
'''
torch.split(t1, 2)
'''
(tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]),)
'''
torch.split(t1, 5, dim=1)
'''
(tensor([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]]), tensor([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]]))
'''
# 指定划分列表,依次表示有 1,2,3,4 个长度
torch.split(t1, [1, 2, 3, 4], dim=1)
'''
(tensor([[1.],
[1.]]), tensor([[1., 1.],
[1., 1.]]), tensor([[1., 1., 1.],
[1., 1., 1.]]), tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.]]))
'''
增加矩阵维度 unsqueeze
t1 = torch.Tensor([1, 2, 3, 4, 5, 6])
t2 = t1.unsqueeze(dim=0)
# tensor([[1., 2., 3., 4., 5., 6.]])
t3 = t1.unsqueeze(dim=1)
'''
tensor([[1.],
[2.],
[3.],
[4.],
[5.],
[6.]])
'''
# 另一种调用方式
torch.unsqueeze(t1, dim=0)
# tensor([[1., 2., 3., 4., 5., 6.]])
降低纬度(去掉 []) squeeze
属于 unsqueeze 的逆向操作,删除 dim 指定的维度
t1 = torch.Tensor([[[2, 3, 4], [7, 8, 9]]])
t1.shape # torch.Size([1, 2, 3])
t2 = torch.squeeze(t1, dim=0)
t2, t2.shape
# (tensor([[2., 3., 4.], [7., 8., 9.]]), torch.Size([2, 3]))
t3 = torch.squeeze(t1, dim=1)
t3, t3.shape
# (tensor([[[2., 3., 4.], [7., 8., 9.]]]), torch.Size([1, 2, 3]))
t4 = t1.squeeze(dim=0)
t4, t4.shape
# (tensor([[2., 3., 4.], [7., 8., 9.]]), torch.Size([2, 3]))
获取沿着某个维度切片后 所有的切片 unbind
t1 = torch.rand(2, 2, 3)
'''
tensor([[[0.53095, 0.25374, 0.68720],
[0.69803, 0.41977, 0.72966]],
[[0.62927, 0.88989, 0.74201],
[0.49337, 0.88015, 0.29941]]])
'''
torch.unbind(t1, dim=1)
'''
(tensor([[0.53095, 0.25374, 0.68720],
[0.62927, 0.88989, 0.74201]]), tensor([[0.69803, 0.41977, 0.72966],
[0.49337, 0.88015, 0.29941]]))
'''
torch.unbind(t1, dim=0)
'''
(tensor([[0.53095, 0.25374, 0.68720],
[0.69803, 0.41977, 0.72966]]), tensor([[0.62927, 0.88989, 0.74201],
[0.49337, 0.88015, 0.29941]]))
'''
拼接 cat
t1 = torch.ones(2,3)
torch.cat([t1, t1]) # (4, 3)
'''
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
'''
torch.cat([t1, t1], dim=1) # (2, 6)
'''
tensor([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]])
'''
按指定维度切分 chunk
# 按照第二个维度,切分为5个tensor
t1 = torch.ones(2, 10)
torch.chunk(t1, 5, dim=1)
'''
(tensor([[1., 1.],
[1., 1.]]), tensor([[1., 1.],
[1., 1.]]), tensor([[1., 1.],
[1., 1.]]), tensor([[1., 1.],
[1., 1.]]), tensor([[1., 1.],
[1., 1.]]))
'''
聚合 gather
t1 = torch.Tensor([[33, 6, 9], [1, 5, 8]])
# 原tensor:t1, 维度:1, 索引:[[0, 1], [2, 1]]
torch.gather(t1, 1, torch.LongTensor([[0, 1], [2, 1]]))
# tensor([[33., 6.], [ 8., 5.]])
改变尺寸
- view
- reshape
- transpose 转置
- permute
1、view
view()
返回的新Tensor
与源Tensor
虽然可能有不同的size
,但是是共享data
的,也即更改其中的一个,另外一个也会跟着改变。(顾名思义,view仅仅是改变了对这个张量的观察角度,内部数据并未改变)**
t1 = torch.ones(4,5)
# -1代表自动匹配个数
t2 = t1.view(-1, 10)
# tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
t3 = t1.view(4, -1)
# tensor([[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]])
t4 = t1.view(5,4)
t5 = t1.view(3,3)
# RuntimeError: shape '[3, 3]' is invalid for input of size 20
t1 += 1
t1, t2
# t1 : tensor([[2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.]]),
# t2 : tensor([[2., 2., 2., 2., 2., 2., 2., 2., 2., 2.], [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.]])
Pytorch还提供了一个reshape()
可以改变形状,但是此函数并不能保证返回的是其拷贝,所以不推荐使用。
所以如果我们想返回一个真正新的副本(即不共享data内存),推荐先用clone
创造一个副本然后再使用view
。参考此处 SOF
t1_cp = t1.clone().view(2, -1)
t1 -= 1
# t1 : tensor([[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]])
# t2 : tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
2、reshape
t1 = torch.ones(2,3,5)
'''
tensor([[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]]])
'''
t2 = torch.reshape(t1,((1,5,6)))
'''
tensor([[[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]]])
'''
t3 = torch.reshape(t1,((1,-1,6))) # 结果同 t2
索引、切片
我们还可以使用类似NumPy的索引操作来访问Tensor
的一部分。
需要注意的是:索引出来的结果 与 原数据共享内存,也即修改一个,另一个会跟着修改。
函数 | 功能 |
index_select(input, dim, index) | 在指定维度dim上选取,比如选取某些行、某些列 |
masked_select(input, mask) | 例子如上,a[a>0],使用ByteTensor进行选取 |
nonzero(input) | 非0元素的下标 |
gather(input, dim, index) | 根据index,在dim维度上选取数据,输出的size与index一样 |
t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
# t1 : tensor([[1, 2, 3], [4, 5, 6]])
t2 = t1[1,2] # tensor(6)
t3 = t1[0, :]
# tensor([1, 2, 3])
t3 += 1
# t3 : tensor([2, 3, 4])
# t1 tensor([[2, 3, 4], [4, 5, 6]])
t1 = torch.tensor([[[1, 2, 3], [4, 5, 6]],
[[7, 8, 9], [10, 11, 12]]])
t1.shape # torch.Size([2, 2, 3])
t1[1, 0, 2] # tensor(9)
t1[:, :, 2]
'''
tensor([[ 3, 6],
[ 9, 12]])
'''
高级选择函数
-
index_select(input, dim, index)
, 在指定维度dim上选取,比如选取某些行、某些列 -
masked_select(input, mask)
, 例子如上,a[a>0],使用ByteTensor进行选取 -
nonzero(input)
, 非0元素的下标 -
gather(input, dim, index)
, 根据index,在dim维度上选取数据,输出的size与index一样
按照索引选择目标数据 index_select
t1 = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
'''
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
'''
t1[1,2] # tensor(6)
# 0 维度的第0个数据
torch.index_select(t1, 0, torch.LongTensor([0]))
# 第1列的元素排在 第0列; 0-1, 2-2
torch.index_select(t1, 1, torch.LongTensor([1, 0, 2]))
'''
tensor([[2, 1, 3],
[5, 4, 6],
[8, 7, 9]])
'''
torch.index_select(t1, 1, torch.LongTensor([2, 1, 0]))
'''
tensor([[3, 2, 1],
[6, 5, 4],
[9, 8, 7]])
'''
选出满足条件的矩阵元素 masked_select
t1 = torch.rand(2, 4)
t1
'''
tensor([[0.00894, 0.14170, 0.06343, 0.57149],
[0.99475, 0.81315, 0.28624, 0.73843]])
'''
mask = t1.ge(0.5)
mask
'''
tensor([[False, False, False, True],
[ True, True, False, True]])
'''
torch.masked_select(t1, mask)
# tensor([0.57149, 0.99475, 0.81315, 0.73843])
找出矩阵中的非零元素的索引 nonzero
t1 = torch.Tensor([[0.48282, 0, 0.45506, 0.48478],
[0, 0.23411, 0, 0.44914]])
torch.nonzero(t1)
# 返回的行数为原 Tensor 中非零元素的个数,列数为原 Tensor 的维度
# [0,0] 第0维的第 0 个数据非 0
tensor([[0, 0],
[0, 2],
[0, 3],
[1, 1],
[1, 3]])
t1 = torch.Tensor([[[0.48282, 0], [0.45506, 0.48478]],
[[0, 0.23411], [0, 0.44914]]])
torch.nonzero(t1)
# [0,0] 第0维的索引 [0, 0] 个数据非 0
tensor([[0, 0, 0],
[0, 1, 0],
[0, 1, 1],
[1, 0, 1],
[1, 1, 1]])
数学计算
t1 = torch.tensor([[[1, 2., 3.], [4, 5, 6]]])
a.min() # tensor(1)
a.max() # tensor(6)
# 浮点数的 tensor 才能获取标准差;整数无法获取
a.std() # tensor(1.8708)
加法
t1 = torch.randn(2, 3)
# tensor([[-0.4300, -0.8063, 1.4317], [ 0.8179, 0.5675, -2.0124]])
t1 + 1
# tensor([[ 0.5700, 0.1937, 2.4317], [ 1.8179, 1.5675, -1.0124]])
t2 = torch.ones(2, 3)
# tensor([[1., 1., 1.], [1., 1., 1.]])
# 加法方式 1
t1 + t2
# tensor([[ 0.5700, 0.1937, 2.4317], [ 1.8179, 1.5675, -1.0124]])
# 加法方式 2
torch.add(t1, t2)
# tensor([[ 0.5700, 0.1937, 2.4317], [ 1.8179, 1.5675, -1.0124]])
# 加法方式 3
# 提前设定一个空的张量
result = torch.empty(2, 3)
# 将空的张量作为加法的结果存储张量
torch.add(t1, t2, out=result)
# tensor([[ 0.5700, 0.1937, 2.4317], [ 1.8179, 1.5675, -1.0124]])
# 加法方式 4 - in-place (原地置换)
# 注意: 所有in-place的操作函数都有一个下划线的后缀.
# 比如 t1.copy_(y), t1.add_(y), 都会直接改变x的值.
y.add_(x)
# t2 : tensor([[ 0.5700, 0.1937, 2.4317], [ 1.8179, 1.5675, -1.0124]])
t1[:, 1]
tensor([-0.8063, 0.5675])
# tensor([[-0.4300, -0.8063, 1.4317], [ 0.8179, 0.5675, -2.0124]])
乘法
t1 = torch.tensor([[1, 2], [3, 4]])
t2 = torch.tensor([[5, 6], [7, 8]])
t1 * 2
# tensor([[2, 4], [6, 8]])
# 对应元素相乘
t1 * t2
# tensor([[ 5, 12],
# [21, 32]])
torch.mul(t1, t2) # 结果同上
# 矩阵乘法
t3 = torch.mm(t1, t2)
# c tensor([[19, 22],
# [43, 50]])
t4 = torch.matmul(t1, t2) # 结果同上
绝对值、向上取整、向下取整、相反数、倒数、平方根、平方根倒数
t1 = torch.Tensor([-1, 0.5, -2.3, 0.99, 0.35])
# 绝对值
torch.abs(t1)
# tensor([1.0000, 0.5000, 2.3000, 0.9900, 0.3500])
# 向上取整
torch.ceil(t1)
# tensor([-1., 1., -2., 1., 1.])
# 向下取整
torch.floor(t1)
# tensor([-1., 0., -3., 0., 0.])
# 夹逼函数
# 每个元素限制在给定的区间范围内,小于范围下限的被强制设置为下限值;大于范围上限的被强制设置为上限值。
torch.clamp(t1, -5.5, 5.5)
# tensor([-1.0000, 0.5000, -2.3000, 0.9900, 0.3500])
# 相反数
torch.neg(t1)
# tensor([ 1.0000, -0.5000, 2.3000, -0.9900, -0.3500])
# 倒数
torch.reciprocal(t1)
# tensor([-1.0000, 2.0000, -0.4348, 1.0101, 2.8571])
# 平方根倒数
torch.rsqrt(t1[t1>0])
# tensor([1.4142, 1.0050, 1.6903])
# 平方根
torch.sqrt(t1)
# tensor([ nan, 0.7071, nan, 0.9950, 0.5916])
# 返回浮点数小数部分
torch.frac(t1)
# tensor([ 0.0000, 0.5000, -0.3000, 0.9900, 0.3500])
# 四舍五入
torch.round(t1)
# tensor([-1., 0., -2., 1., 0.])
# 截断值,标量x的截断值,比x更接近于0。
torch.trunc(torch.Tensor([-1, 0.5, -2.3, 0.99, 0.35]))
# tensor([-1., 0., -2., 0., 0.])
每个元素加减乘除
t1 = torch.Tensor([2, 3, 4])
# tensor([2., 3., 4.])
torch.add(t1, 3)
# tensor([5., 6., 7.])
torch.mul(t1, 2)
# tensor([4., 6., 8.])
torch.div(t1, 3)
# tensor([0.6667, 1.0000, 1.3333])
# 取余 %
torch.fmod(t1, 3)
# tensor([2., 0., 1.])
torch.remainder(t1, 3)
# tensor([2., 0., 1.])
t2 = torch.Tensor([1.4, 2.3, 5.9])
# tensor([1.4000, 2.3000, 5.9000])
指、对、幂
import math
# 指数运算
torch.exp(torch.Tensor([0, math.log(2)]))
# tensor([1., 2.])
# 自然对数
t1 = torch.Tensor([math.e, math.e**2])
# tensor([2.7183, 7.3891])
# 平滑对数:对输入加1 平滑后再求对数
torch.log1p(t1)
# tensor([1.3133, 2.1269])
# 以2为底的对数
torch.log2(t1)
# tensor([1.4427, 2.8854])
# 以10为底的对数
torch.log10(t1)
# tensor([0.4343, 0.8686])
# 幂运算
torch.pow(t1, 1), torch.pow(t1, 2)
(tensor([2.7183, 7.3891]), tensor([ 7.3891, 54.5982]))
三角函数
t1 = torch.Tensor([-1, 0.5, -2.3, 0.99, 0.35])
torch.cos(t1)
# tensor([ 0.5403, 0.8776, -0.6663, 0.5487, 0.9394])
torch.sin(t1)
# tensor([-0.8415, 0.4794, -0.7457, 0.8360, 0.3429])
# 反余弦
torch.acos(t1)
# tensor([3.1416, 1.0472, nan, 0.1415, 1.2132])
线性插值
t1 = torch.zeros(5).fill_(8)
# tensor([8., 8., 8., 8., 8.])
t2 = torch.arange(5).float()
# tensor([0., 1., 2., 3., 4.])
torch.lerp(t1, t2, 0.5) # 4.5 = 8 + (1-8)*0.5
# tensor([4.0000, 4.5000, 5.0000, 5.5000, 6.0000])
torch.lerp(t1, t2, 0.1) # 7.2 = 8 + (8-0) * 0.1; 7.4 = 8 + (2-8) * 0.1
# tensor([7.2000, 7.3000, 7.4000, 7.5000, 7.6000])
Sigmoid 函数,sign符号函数
# Sigmoid 函数
t1 = torch.arange(-5, 5, 1).float()
t1
# tensor([-5., -4., -3., -2., -1., 0., 1., 2., 3., 4.])
torch.sigmoid(t1)
# tensor([0.0067, 0.0180, 0.0474, 0.1192, 0.2689, 0.5000, 0.7311, 0.8808, 0.9526,
0.9820])
torch.sign(t1)
# tensor([-1., -1., -1., -1., -1., 0., 1., 1., 1., 1.])
规约计算
规约计算一般指分组聚合运算,特点是会使用 分组内 或 所有元素 参与计算,得到统计的结果。
累积 & 累和
t1 = torch.Tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
# tensor([[ 1., 2., 3., 4., 5.],
# [ 6., 7., 8., 9., 10.]])
# 累积
torch.cumprod(t1, dim=0) # 从上往下累积相乘
# tensor([[ 1., 2., 3., 4., 5.],
# [ 6., 14., 24., 36., 50.]])
torch.cumprod(t1, dim=1) # 从前往后累积相乘
# tensor([[1.0000e+00, 2.0000e+00, 6.0000e+00, 2.4000e+01, 1.2000e+02],
# [6.0000e+00, 4.2000e+01, 3.3600e+02, 3.0240e+03, 3.0240e+04]])
# 累和
torch.cumsum(t1, dim=0) # 从上往下累加
# tensor([[ 1., 2., 3., 4., 5.],
# [ 7., 9., 11., 13., 15.]])
torch.cumsum(t1, dim=1) # 从前往后累加
# tensor([[ 1., 3., 6., 10., 15.],
# [ 6., 13., 21., 30., 40.]])
# 所有元素的和
torch.sum(t1)
# tensor(55.)
torch.sum(t1, dim=0)
# tensor([ 7., 9., 11., 13., 15.])
torch.sum(t1, dim=1)
# tensor([15., 40.])
均值、中位数、众数、方差、标准差
t1 = torch.Tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
# 均值
torch.mean(t1)
# tensor(5.5000)
torch.mean(t1, dim=0)
# tensor([3.5000, 4.5000, 5.5000, 6.5000, 7.5000])
torch.mean(t1, dim=1)
# tensor([3., 8.])
# 中位数
torch.median(t1)
# tensor(5.)
# 指定 dim 返回两个Tensor,第一个是中位数,第二个是索引
torch.median(t1, dim=0)
'''
torch.return_types.median(
values=tensor([1., 2., 3., 4., 5.]),
indices=tensor([0, 0, 0, 0, 0]))
'''
torch.median(t1, dim=1)
'''
torch.return_types.median(
values=tensor([3., 8.]),
indices=tensor([2, 2]))
'''
# 众数
torch.mode(t1)
'''
torch.return_types.mode(
values=tensor([1., 6.]),
indices=tensor([0, 0]))
'''
# 方差
torch.var(t1)
# tensor(9.1667)
torch.var(t1, dim=0)
# tensor([12.5000, 12.5000, 12.5000, 12.5000, 12.5000])
torch.var(t1, dim=1)
# tensor([2.5000, 2.5000])
# 标准差
torch.std(t1)
# tensor(3.0277)
torch.std(t1, dim=0)
# tensor([3.5355, 3.5355, 3.5355, 3.5355, 3.5355])
torch.std(t1, dim=1)
# tensor([1.5811, 1.5811])
p-norm 距离
距离公式,常用语模型损失值的计算。计算采用 p-norm 范数。
p=1 为曼哈顿距离,p=2为欧氏距离。默认计算欧式距离。
t1 = torch.Tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
t2 = torch.Tensor([[1, 2, 3, 4, 5], [1, 2, 8, 9, 10]])
torch.dist(t1, t2, p=0)
# tensor(2.)
torch.dist(t1, t2, p=1)
# tensor(10.)
torch.dist(t1, t2, np.inf)
# tensor(5.)
torch.norm(t1, p=1, dim=0) # 上下相加
# tensor([ 7., 9., 11., 13., 15.])
torch.norm(t1, p=1, dim=1) # 左右相加
# tensor([15., 40.])
torch.norm(t1, p=2, dim=0) #
# tensor([ 6.0828, 7.2801, 8.5440, 9.8489, 11.1803])
torch.norm(t1, p=2, dim=1) #
# tensor([ 7.4162, 18.1659])
数值比较运算
大于、小于、等于、不等于
t1 = torch.Tensor([[1, 2, 3], [4, 5, 6]])
t2 = torch.Tensor([[1, 2, 3], [7, 8, 9]])
t3 = torch.Tensor([[4, 5, 6], [7, 8, 9]])
torch.equal(t1, t2)
# False
# 大于,greater than
torch.gt(t1, t2)
# tensor([[False, False, False],
# [False, False, False]])
# 大于等于
torch.ge(t1, t2)
# tensor([[ True, True, True],
# [False, False, False]])
# 小于,less than
torch.lt(t1, t2)
# tensor([[False, False, False],
# [ True, True, True]])
# 小于等于
torch.le(t1, t2)
# tensor([[True, True, True],
# [True, True, True]])
# 是否不相等
torch.ne(t1, t2)
# tensor([[False, False, False],
# [ True, True, True]])
最大值、最小值 max、min
t1 = torch.Tensor([[1, 2, 3], [4, 5, 6]])
torch.max(t1), torch.min(t1)
# (tensor(6.), tensor(1.))
torch.max(t1, dim=0)
'''
torch.return_types.max(
values=tensor([4., 5., 6.]),
indices=tensor([1, 1, 1]))
'''
torch.max(t1, dim=1)
'''
torch.return_types.max(
values=tensor([3., 6.]),
indices=tensor([2, 2]))
'''
排序 sort
t1 = torch.Tensor([[11, 2, 23], [4, 15, 61]])
torch.sort(t1, dim=0, descending=False) # 升序
'''
torch.return_types.sort(
values=tensor([[ 4., 2., 23.],
[11., 15., 61.]]),
indices=tensor([[1, 0, 0],
[0, 1, 1]]))
'''
torch.sort(t1, dim=1, descending=False)
'''
torch.return_types.sort(
values=tensor([[ 2., 11., 23.],
[ 4., 15., 61.]]),
indices=tensor([[1, 0, 2],
[0, 1, 2]]))
'''
topk
选择最大或最小的k个元素作为返回值
t1 = torch.Tensor([[11, 2, 23], [4, 15, 61]])
torch.topk(t1, k=2) # 默认选择最大
'''
torch.return_types.topk(
values=tensor([[23., 11.],
[61., 15.]]),
indices=tensor([[2, 0],
[2, 1]]))
'''
torch.topk(t1, k=2, largest=False) # 选出最小的两个值
'''
torch.return_types.topk(
values=tensor([[ 2., 11.],
[ 4., 15.]]),
indices=tensor([[1, 0],
[0, 1]]))
'''
torch.topk(t1, k=1, dim=0)
'''
torch.return_types.topk(
values=tensor([[11., 15., 61.]]),
indices=tensor([[0, 1, 1]]))
'''
torch.topk(t1, k=1, dim=1)
'''
torch.return_types.topk(
values=tensor([[23.],
[61.]]),
indices=tensor([[2],
[2]]))
'''
矩阵运算
对角矩阵
t1 = torch.rand(2)
# tensor([0.7190, 0.3232])
# diagonal=0,设置为主对角线
torch.diag(t1, diagonal=0)
# tensor([[0.7190, 0.0000],
# [0.0000, 0.3232]])
# diagonal>0,设置为主对角线之上 diagonal 对应的位置
torch.diag(t1, diagonal=1)
# tensor([[0.0000, 0.7190, 0.0000],
# [0.0000, 0.0000, 0.3232],
# [0.0000, 0.0000, 0.0000]])
torch.diag(t1, diagonal=2)
# tensor([[0.0000, 0.0000, 0.7190, 0.0000],
# [0.0000, 0.0000, 0.0000, 0.3232],
# [0.0000, 0.0000, 0.0000, 0.0000],
# [0.0000, 0.0000, 0.0000, 0.0000]])
# diagonal<0,设置为主对角线之下 diagonal 对应的位置
torch.diag(t1, diagonal=-1)
# tensor([[0.0000, 0.0000, 0.0000],
# [0.7190, 0.0000, 0.0000],
# [0.0000, 0.3232, 0.0000]])
矩阵的迹
t1 = torch.randn(2, 4)
# tensor([[-0.8954, 0.6590, 0.0918, 0.5809],
# [ 0.5339, -0.8087, -0.4212, 2.0023]])
torch.trace(t1)
# tensor(-1.7041)
上三角矩阵和下三角矩阵
# diagonal 控制对角线 偏移的位置
t1 = torch.randn(3, 4)
# tensor([[ 0.2944, 1.0727, -0.5332, 2.2292],
# [-0.3672, 1.5228, -1.1491, 0.2756],
# [ 0.4644, -0.1443, -2.5940, -2.1068]])
torch.tril(t1, diagonal=1)
# tensor([[ 0.2944, 1.0727, 0.0000, 0.0000],
# [-0.3672, 1.5228, -1.1491, 0.0000],
# [ 0.4644, -0.1443, -2.5940, -2.1068]])
torch.tril(t1, diagonal=-1)
# tensor([[ 0.0000, 0.0000, 0.0000, 0.0000],
# [-0.3672, 0.0000, 0.0000, 0.0000],
# [ 0.4644, -0.1443, 0.0000, 0.0000]])
矩阵的乘积 mm
t1 = torch.Tensor([[1, 2, 3], [4, 5, 6]])
t2 = torch.Tensor([[5], [3], [2]])
torch.mm(t1, t2) # 17 = 1*5 + 2*3 + 3*2
# tensor([[17.],
# [47.]])
特征值及特征向量
t1 = torch.Tensor([[1, 2, 3], [6, 5, 4], [9, 5, 1]])
torch.eig(t1)
'''
torch.return_types.eig(
eigenvalues=tensor([[ 1.1262e+01, 0.0000e+00],
[-4.2621e+00, 0.0000e+00],
[-6.1734e-07, 0.0000e+00]]),
eigenvectors=tensor([]))
'''
torch.eig(t1, eigenvectors=True)
'''
torch.return_types.eig(
eigenvalues=tensor([[ 1.1262e+01, 0.0000e+00],
[-4.2621e+00, 0.0000e+00],
[-6.1734e-07, 0.0000e+00]]),
eigenvectors=tensor([[ 0.3216, 0.4729, 0.4082],
[ 0.7090, 0.0729, -0.8165],
[ 0.6275, -0.8781, 0.4082]]))
'''
广播机制
广播机制即不同维度、长度的 Tensor,在满足一定规则的前提下,能够自动进行维度和长度的扩充。
t1 = torch.Tensor([1, 2, 3])
t2 = torch.Tensor([4, 5, 6])
t1 + t2 # tensor([5., 7., 9.])
t1 * t2 # tensor([ 4., 10., 18.])
其它
设置打印选项
torch.set_printoptions(precision=5, threshold=100, linewidth=80, edgeitems=4)
torch.DoubleTensor(100, 300)
'''
tensor([[ 0.00000e+00, 2.18717e-314, 1.22392e-318, nan,
..., -5.26032e+127, -4.12046e+127, -5.26352e+127,
3.99349e-237],
[ 1.31275e+170, 3.03984e-298, 4.43398e+228, 4.66241e+24,
..., 1.52293e+256, 9.08365e+223, 1.77568e+248,
3.43530e+228],
...
[ 4.03717e-270, 3.19126e-241, 2.31582e-289, 3.95581e+252,
..., 8.03757e+165, 8.80067e+199, 2.86524e+161,
1.66042e+243]])
'''
全局设置 Tensor 数据类型
torch.set_default_tensor_type(torch.DoubleTensor)
t1 = torch.Tensor(2)
# tensor([2.2755e+161, 6.7866e+199])
t1.dtype # torch.float64
随机抽样
设置随机种子
# 手动设置种子
torch.manual_seed(123)
seed = torch.initial_seed() # 123
# 返回随机生成器状态
state = torch.get_rng_state()
# tensor([123, 0, 0, 0, ..., 0, 0, 0, 0], dtype=torch.uint8)
伯努利分布采样
伯努利分布结果只有 0 和 1,第一个参数的概率是p,且 0<=p<=1
torch.manual_seed(123)
t1 = torch.rand(3, 3)
'''
tensor([[0.36890, 0.01337, 0.59178],
[0.09264, 0.47245, 0.52203],
[0.60508, 0.53130, 0.94855]])
'''
t2 = torch.bernoulli(t1)
'''
tensor([[1., 0., 1.],
[0., 1., 1.],
[1., 0., 1.]])
'''
多项式分布抽样
torch.multinomial 函数参数说明
- 第一个参数是多项式权重;可以是向量,也可以是矩阵。权重决定了对下标的抽样。
- 如果是向量,replacement 代表是否有放回的抽样;
- replacement=True,结果行数为1,列数由 num_samples 决定;
- replacement=False, 行数为1,列数<=权重长度
w1 = torch.Tensor([20, 10, 3, 2])
torch.multinomial(w1, num_samples=3, replacement=False)
# tensor([1, 0, 2])
torch.multinomial(w1, num_samples=10, replacement=True)
# tensor([1, 0, 0, 0, 3, 0, 0, 0, 1, 0])
w2 = torch.Tensor([[20, 10, 3, 2], [30, 4, 5, 6]])
torch.multinomial(w2, num_samples=4, replacement=False)
'''
tensor([[1, 0, 2, 3],
[0, 2, 3, 1]])
'''
torch.multinomial(w2, num_samples=15, replacement=True)
'''
tensor([[1, 1, 1, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 3],
[2, 0, 0, 3, 0, 1, 3, 2, 2, 0, 0, 0, 0, 2, 0]])
'''
标准分布抽样
# 均值为0.5,方差为 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
torch.normal(mean=0.5, std=torch.arange(0.1, 1, 0.0001))
# tensor([0.48034, 0.44650, 0.56860, 0.57181, ..., 0.35206, 1.26491, 1.48555, 2.14253])
# 均值为 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9],方差为 0.5
torch.normal(mean=torch.arange(0.1, 1, 0.1), std=0.5)
# tensor([0.00936, 0.29426, 0.80918, 1.27463, 0.18718, 1.13891, 0.50415, 1.32652, 0.71879])
# 均值为 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9],方差为 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
torch.normal(mean=torch.arange(0.1, 1, 0.1), std=torch.arange(0.1, 1, 0.1))
# tensor([ 0.11960, 0.52833, -0.29105, 0.60408, 1.43937, 0.51561, 1.04438, 0.85068, 0.45567])
import matplotlib.pyplot as plt
t1 = torch.normal(mean=0.5, std=torch.arange(0.1, 1, 0.0001))
plt.plot(torch.arange(0.1, 1, 0.0001).data.numpy(), t1.data.numpy() )
plt.show()
在 gpu/cpu 运行
# 实例化 device
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu" )
# device(type='cpu')
# 在 device 上创建 tensor
t1 = torch.ones([2, 3], device=device)
# 将已创建的 tensor 转移到 device
t2 = t2.to(device)
2022-02-01