Pytorch tensor全面了解 | tensor的构建方法大全
在我们对某一功能进行测试或展示时
通常都需要构建一系列
tensor
用于小型数据测试
以验证功能的正确性或展示的可行性
因此本文就梳理了
pytorch
中构建
tensor
的一系列方法
数据转tensor
将存储在别的结构中的数据转为
tensor
的格式
tensor
内部拷贝源数据并构建返回相应的
tensor
必要参数(Parameters)
-
data
- 传入的结构类型 -array
、list
、tuple
、scalar
(标量)…
可选参数(Keywords)
-
dtype
- 生成的数据类型 -torch.float
、.double
、.int
、.long
… -
requires_grad
- 是否需要计算梯度 -
device
- 表示tensor
所在的设备 -torhc.device('cpu')
、.device('cuda')
Test
a = torch.tensor(1.0)
b = torch.tensor([1, 2, 3], dtype=torch.float64, device=torch.device('cuda:0'))
c = torch.tensor(1.66666666666, dtype=torch.float)
d = torch.tensor(1.66666666666, dtype=torch.double)
e = torch.tensor([])
Output
a = tensor(1.)
b = tensor([1., 2., 3.], device='cuda:0', dtype=torch.float64)
c = tensor(1.6667)
d = tensor(1.6667, dtype=torch.float64)
e = tensor([])
sparse_coo_tensor
将数据转化为稀疏张量
Parameters:
-
indices
-N
个非零值的索引 -shape(2, N)
-
values
- 值 - 索引对应的N
个值 -
size
- 稀疏tensor
的形状 - 默认为符合输入要求的最小形状
Keywords
:
dtype - device - requires_grad
Test 1
i = torch.tensor([[0, 1, 1], [2, 0, 2]])
v = torch.tensor([3, 4, 5], dtype=torch.float32)
torch.sparse_coo_tensor(i, v)
Output 1
tensor(indices=tensor([[0, 1, 1],
[2, 0, 2]]),
values=tensor([3., 4., 5.]),
size=(2, 3), nnz=3, dtype=torch.float32, layout=torch.sparse_coo)
# nnz: number of nonzero - 存储非零值的数目
# layout: 表示在内存中的布局形式 - 先放一放
Test 2 尝试手动指定size
i = torch.tensor([[0, 1, 1],
[2, 0, 2]])
v = torch.tensor([3, 4, 5],dtype=torch.float32)
torch.sparse_coo_tensor(i, v, [2, 4])
Output 2
tensor(indices=tensor([[0, 1, 1],
[2, 0, 2]]),
values=tensor([3., 4., 5.]),
size=(2, 4), nnz=3, dtype=torch.float32, layout=torch.sparse_coo)
as_tensor
与
tensor
方法类似,但
as_tensor
可能不会拷贝源数据(共享内存),如果更改数据,可能引发未知的错误。不进行拷贝的条件如下:
-
数据为:
ndarray
类型 且 数据所处设备为CPU
-
数据为:
tensor
类型 且 数据类型、数据所处设备与默认设置一致
建议不必管上述条件
可默认所有生成的数据都没有拷贝源数据
如果出现必须拷贝的地方使用
copy.deepcopy()或 torch.clone()
应对
Test 1
# Test 1
a = np.array([1, 2, 3])
t = torch.as_tensor(a)
print(a, t)
t[0] = -1
print(a, t)
Output 1
a = [1 2 3]
t = tensor([1, 2, 3])
# 并没有发生拷贝
a = [-1 2 3]
t = tensor([-1, 2, 3])
Test 2
# Test 2
a = np.array([1, 2, 3])
t = torch.as_tensor(a, device=torch.device('cuda'))
print(a, t)
t[0] = -1
print(a, t)
Output 2
a = [1 2 3]
t = tensor([1, 2, 3], device='cuda:0')
# 没有发生拷贝:因为所处设备不一致
a = [1 2 3]
t = tensor([-1, 2, 3], device='cuda:0')
from_numpy
将
ndarray
转换为
tensor
共享内存
不能修改底层容器的大小 -
The returned tensor is not resizable.
Test
a = np.array([1, 2, 3, 4])
t = torch.from_numpy(a)
print(a, t)
t[0] = -99
print(a, t)
Output
a = [1 2 3 4]
t = tensor([1, 2, 3, 4])
# 共享内存
a = [-99 2 3 4]
t = tensor([-99, 2, 3, 4])
complex
构建复数
tensor
Parameters
-
real
- 实部 -tensor
-float or double
-
imag
- 虚部 -tensor
-the same dtype as real part
Tips:
real
和
imag
的数据类型必须要一致哦
类型转换
-
float
将转化为torch.complex64
-
double
将转化为torch.complex128
Test
real = torch.tensor([1, 2], dtype=torch.float)
imag = torch.tensor([3, 4], dtype=torch.float)
z = torch.complex(real, imag)
Output
z = tensor([1.+3.j, 2.+4.j])
z.type = torch.complex64
生成指定tensor
生成指定
tensor
:生成tensor后并填入指定的数值
zeros ones empty
上面这三个方法用法大体一致
Parameters
-
size
-sequence of integers
empty
返回的未经初始化的值,仅仅分配了空间
为什么有的
shape
的输入需要用
tuple
表示,有的直接输入就行了呢
因为只有这一个位置参数,后续的参数输入需要指定参数名称,因此size不必封装为tuple
Test
a = torch.ones(1, 2, 3, dtype=torch.float)
b = torch.zeros(2)
c = torch.empty(1)
Output
a = tensor([[[1., 1., 1.],
[1., 1., 1.]]])
b = tensor([0., 0.])
c = tensor([4.2195e-08])
full
用所给的值
fill_value
进行填充生成
tensor
- 因为有两个必须输入的值,因此所输入的size必须封装进一个tuple
Parameters
-
size
-(sequence of integers)
-
fill_value
- 填充入tensor
的数值
Test
a = torch.full((2, 3), fill_value=10.)
b = torch.full((2, 3), 10.)
Output
a = tensor([[10., 10., 10.],
[10., 10., 10.]])
b = tensor([[10., 10., 10.],
[10., 10., 10.]])
*_like
该类方法一共有四种:
-
zeros_like
-
ones_like
-
empty_like
-
full_like
简单理解如下:
torch.zeros_like(input) == torch.zeros(input.size(), dtype=input.dtype, layout=input.layout, device=input.device)
即利用输入
tensor
的属性生成新的
tensor
full_like
中的
fill_value
仍需要输入哦~
Test
a = torch.ones(2, 2)
b = torch.zeros_like(a)
c = torch.full_like(a, 10)
Output
a = tensor([[1., 1.],
[1., 1.]])
b = tensor([[0., 0.],
[0., 0.]])
c = tensor([[10., 10.],
[10., 10.]])
arange
这就和
numpy
中的
arange
一致啦,简单介绍下
Parameter
-
start
- 序列起始值 - 初始值为0 -
end
- 序列结束值 -
step
- 步长
Test
# 输入 1 个参数 - start(0) end(10) step(1)
a = torch.arange(10)
# 输入 2 个参数 - start(3) end(5) step(1)
b = torch.arange(3, 5)
# 输入 3 个参数 - start(3) end(9) step(3)
c = torch.arange(3, 9, 3)
Output
a = tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
b = tensor([3, 4])
c = tensor([3, 6])
linspace
给定起始值
s
、结束值
e
与数值个数
N
,生成线性等分向量。间距大小由数值个数
N
决定
Test
# 输入 2 个参数 - start(3) end(5) size(100)
a = torch.linspace(10, 100)
# 输入 3 个参数 - start(10) end(100) size(10)
b = torch.linspace(10, 100, 10)
Output
a = tensor([ 10.0000, 10.9091, ... , 99.0909, 100.0000])
b = tensor([ 10., 20., 30., 40., 50., 60., 70., 80., 90., 100.])
logspace
和
linspace
类似,看样例就行啦
[base^{start}, base^{end}] - \text{size}
Test
# torch.logspace(start=1, end=10,steps=10, base=2)
# 两个参数 start(1) end(2) steps(100) base(10)
a = torch.logspace(1, 2)
# 三个参数 start(1) end(3) steps(3) base(10)
b = torch.logspace(1, 3, 3)
# 四个参数 start(1) end(10) steps(10) base(2)
c = torch.logspace(1, 10, 10, 2)
Output
a = tensor([ 10.0000, 10.2353, ..., 97.7010, 100.0000])
b = tensor([ 10., 100., 1000.])
c = tensor([ 2., 4., 8., 16., 32., 64., 128., 256., 512., 1024.])
eye
生成二维矩阵,对角线上为1,其它地方为0
Parameters
-
n
-int
- 矩阵的行数 -
m
-default(n):
默认等于n
- 矩阵的列数,默认 -
out, dtype, layout, device, requires_grad
eye
生成的可并不完全是单位阵哦,因为他的行数
n
可以不等于列数
m
Test
# 一个参数 n(2) m=n(2)
a = torch.eye(2)
# 两个参数 n(2) m(3)
b = torch.eye(2, 3)
Output
# Output
a = tensor([[1., 0.],
[0., 1.]])
b = tensor([[1., 0., 0.],
[0., 1., 0.]])
随机生成tensor
不在意
tensor
中的数据,常用作各类
tensor
操作测试
rand & rand_like
随机为
tensor
填充数据,数据符合
[0,1]
上的均匀分布 (
out_i \sim U(0, 1)
)
Parameters -
size
-
ints
一系列整数
rand_like
的用法与上文讲述一致
Test
a = torch.rand(2, 2)
b = torch.rand_like(a)
Output
a = tensor([[0.8395, 0.9932],
[0.3633, 0.6407]])
b = tensor([[0.0679, 0.1779],
[0.8335, 0.6131]])
randn & randn_like
随机为
tensor
填充数据,数据符合标准正太分布 (
out_i \sim N(0, 1)
)
randn_like
的用法与上文讲述一致
Test
a = torch.randn(2, 2)
b = torch.randn_like(a)
Output
a = tensor([[ 1.3448, -0.3945],
[ 0.9157, -0.3566]])
b = tensor([[ 0.4449, 1.2405],
[ 1.3466, -0.0139]])
randint & randint_like
随机为
tensor
填充数据,数据为整数且介于
low
与
high
之间(
out_i \in [low, high)
)
Parameters
-
low
-default(0)
-
high
-int
-
size
-(ints)
- 为tuple
元祖的形式
Test
# low(0) high(10) size(2, 3)
a = torch.randint(10, (3, 4))
# low(2) high(4) size(2, 3)
b = torch.randint(2, 4, (2, 3))
Output
a = tensor([[8, 8, 7],
[5, 5, 5]])
b = tensor([[3, 2, 2],
[3, 2, 3]])
bernoulli
伯努利分布 /
0-1
分布
P(X=1) =p \\ P(X=0)=1-p
简单理解(
p=0.5
):伯努利分布可以理解为一次硬币实验,那么相当于对
tensor
中的每个元素做一次硬币实验得到的结果即为该元素的值
-
Parameter -
input
-tensor
- 输入表示为1的概率p
- out_i = Bernoulli(p=input_i)
Test
p = torch.rand(2, 3)
b = torch.bernoulli(p)
Output
p = tensor([[0.4427, 0.9014, 0.1100],
[0.3531, 0.6641, 0.2243]])
b = tensor([[1., 1., 0.],
[0., 1., 0.]])
normal
正太分布
Parameters
-
mean
-tensor
- 每个输出元素所在正太分布的均值 -
std
-tensor
- 每个输出元素所在正太分布的标准差 -
size
-(ints)
-mean
和std
一致时可以给定size
Test 1
# 一一对应
a = torch.normal(mean=torch.arange(1., 11.), std=torch.linspace(0, 1, 10))
# 支持广播
b = torch.normal(mean=torch.rand(2), std=torch.rand(2, 2))
c = torch.normal(mean=torch.rand(2, 2), std=0.6)
Output 1
a = tensor([1.0000, 2.0786, 3.1498, 3.6431, 5.8021])
b = tensor([[ 0.9664, 0.4581],
[ 1.0587, -0.9274]])
c = tensor([[ 0.7546, -0.4395],