PyTorch最基本的操作对象是Tensor(张量)。张量是一个数字容器,同时也是定义张量转换来生成新张量的一组规则。
在数学中标量是只有大小没有方向的量;向量时有大小和方向的量;矩阵是由多个向量组成的。在PyTorch中标量就可以视为零阶的张量,向量可以视为一阶张量,矩阵就是二阶张量。
优点:在PyTorch中支持GPU运算和自动求梯度等功能。
Variable是torch .autograd中的数据类型主要用于封装Tensor,进行自动求导(0.4.0后已并入tensor,不再存在),六大属性:
data:被包装的Tensor
grad:data的梯度
grad_fn:创建Tensor的Function,是自动求导的关键
require_grad:指示是否需要梯度
is_leaf:指示是否是叶子结点(张量)
Tensor除了上述属性,还有以下三个属性:
dtype:张量的数据类型
shape:张量的形状
device:张量所在的设备,GPU/CPU,是加速的关键
torch.tensor(
data,
dtype = None,
device = None,
require_grad = False,
pin_memory = False ## 是否依赖锁页内存
)
flag = True
if flag:
arr = np.ones([3,3])
print('arr数据类型:', arr.dtype)
t = torch.Tensor(arr, device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu'))
print(t)
from_numpy创建张量
【注意】从torch.from_numpy创建的tensor于原ndarray共享内存,当修改其中一个的数据,另外一个也将会被改动=。
flag = True
if flag:
arr = np.array([[1,2,3],[2,3,4]])
t = torch.from_numpy(arr)
print(t)
arr[0][0] = 0
print(t) ## 数据也随之变化
等值数列
torch.zeros(
*size, ## 形状
out = None, ## 输出的张量
dtype = None,
layout = torch.strided, ## 内存中的布局形式
device = None,
require_grad = False
)
flag = True
if flag:
out_t = torch.Tensor([1])
t = torch.zeros([3,3], out=out_t)
print(t, '\n', out_t)
print(id(t), id(out_t), id(t) == id(out_t))
输出结果:
tensor([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) tensor([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) 2305522661552 2305522661552 True
表明 t 和 out_t有同一个存储地址,只是命名不同。
torch.zeros_like(
input,
dtype = None,
layout = torch.strided, ## 内存中的布局形式
device = None,
require_grad = False
)
还有torch.ones、torch.ones_like、torch.full、torch.full_like等,可以使用。
flag = True
if flag:
t = torch.full((3,3), 10)
print(t)
等差数列
创建等差的一维张量
torch.arange(
start = 0,
end, ## 不包含end,类似np.arange函数
step,
out=None,
dtype = None,
layout = torch.strided, ## 内存中的布局形式
device = None,
require_grad = False
)
均分数列
创建均分的一维张量
torch.linspace(
start = 0,
end, ## 包含end
steps, ## 数列长度
out=None,
dtype = None,
layout = torch.strided, ## 内存中的布局形式
device = None,
require_grad = False
)
对数均分数列
创建对数均分的一维张量
torch.linspace(
start = 0,
end, ## 包含end
steps = 100, ## 数列长度
base=10.0, ## 对数函数的底
out=None,
dtype = None,
layout = torch.strided, ## 内存中的布局形式
device = None,
require_grad = False
)
对角矩阵
二维张量(默认为方阵)
torch.eye(
n, ## 行数
m = None, ## 列数
out=None,
dtype = None,
layout = torch.strided, ## 内存中的布局形式
device = None,
require_grad = False
)
生成正态分布张量
t = torch.normal(mean=0, std=1,size=(3,3))
mean = torch.arange(1, 5, dtype=torch.float)
std = torch.arange(1, 5, dtype=torch.float)
t_normal = torch.normal(mean, std)
t_normal
t_normal = tensor([ 1.3724, 3.6892, 0.4200, -5.6512])
均匀分布
torch.rand、torch.rand_like:生成0-1均匀分布
torch.randint、torch.randint_like:生成【low,high)之间的整数均匀分布
随机分布
torch.randperm:生成从0到n-1的随机排列
t = torch.randperm(n=5, dtype=torch.float)
t = tensor([1., 3., 2., 4., 0.])
伯努利分布(0-1分布)
t = torch.bernoulli(input=torch.linspace(0,1,10))
torch.cat/torch.stack
torch.cat(
tensors,
dim = 0, ## 拼接的维度
out = None
)
torch.cat:将张量按维度dim进行拼接
torch.stack:在新创建的维度dim上进行拼接
t = torch.ones((2,3))
t_0 = torch.cat([t,t], dim=0) ## 按行拼接
t_1 = torch.cat([t,t], dim=1) ## 按列拼接
torch.chunk
torch.chunk(
tensors,
chunks, ## 切分的分数
dim = 0 ## 切分维度
)
torch.chunk将张量按维度dim进行平均切分
torch.chunk(t_1, chunks=3, dim=1)
切分结果:
(tensor([[1., 1.], [1., 1.]]), tensor([[1., 1.], [1., 1.]]), tensor([[1., 1.], [1., 1.]]))
torch.split
torch.split(
tensors,
split_size_or_sections, ## 为int时,表示每一份的长度;为list时,按list元素切分
dim = 0 ## 切分维度
)
torch.split(t_1, split_size_or_sections=[2,3,1], dim=1)
切分结果:
(tensor([[1., 1.], [1., 1.]]), tensor([[1., 1., 1.], [1., 1., 1.]]), tensor([[1.], [1.]]))
t = torch.randint(0,9,size=(3,3))
idx = torch.tensor([0,2], dtype = torch.long)
t_select = torch.index_select(t, dim=0, index=idx)
print(t)
print(t_select)
结果:
tensor([[3, 0, 0], [2, 0, 3], [5, 6, 8]]) tensor([[3, 0, 0], [5, 6, 8]])
torch.masked_select
按mask中的True进行索引
t = torch.randint(0,9,size=(3,3))
mask = t.ge(5) ## 判断元素是否大于等于5
t_select = torch.masked_select(t, mask=mask)
print(t)
print(t_select)
返回:
tensor([[0, 7, 5], [0, 2, 8], [8, 8, 0]]) tensor([7, 5, 8, 8, 8])
torch.reshape
变换张量形状
t = torch.randint(0,9,size=(3,3))
torch.reshape(t, (1,9))
torch.transpose
交换张量的两个维度(矩阵的转置)
torch.transpose(input, dim0, dim1)
torch.t
2维张量转置,对矩阵而言,等价于
torch.transpose(input, 0, 1)
torch.squeeze
压缩长度为1的维度(轴)
若dim为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除;
t = torch.randint(0,9,size=(3,3,1))
t_s = torch.squeeze(t)
print(t.shape)
print(t_s.shape)
torch.unsqueeze
依据dim扩展维度,长度为1