Pytorch 零基础学习系列 之 创建张量

在深度学习中,神经网路结构是基础;在Pytorch中,张量是构建神经网络的基础 。从本质上讲,Pytorch就是一个处理张量的库。一个张量可以是一个数字、向量、矩阵或者任何n维数组。比较重要的一点是张量可以在GPU上进行计算。

例如,下图分别展示了1维张量,2维张量和3维张量:

如何创建一般张量?

方法一

(1) 导入 pytorch 和 numpy

import torch
import numpy as np

(2) 张量相关参数

torch.tensor(data, dtype = None, device = None, requires_grad = False, pin_memory = False)

其中,

  • data:数据,可以是列表list,numpy的 ndarray
  • dtype:数据类型,默认与data数据类型一致
  • device:所在设备,GPU/CPU
  • requires_grad:是否需要梯度,神经网路经常需要梯度
  • pin_memory:是否存在锁页内存

(3) 使用numpy创建张量

通过 numpy 创建 ndarray,然后转化为张量,数据类型默认与 data一致。

arr = np.ones((3, 3))
print("数据类型:", arr.dtype)
t = torch.tensor(arr)
print(t)

运行结果:

数据类型: float64 tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], dtype=torch.float64)

如果在已经搭建了GPU环境运行,可以通过下面的代码在GPU 上创建张量(创建过程需要几秒的等待时间)

arr = np.ones((3, 3))
print("数据类型:", arr.dtype)
t = torch.tensor(arr, device = 'cuda')
print(t)

运行结果:

数据类型: float64 tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], device='cuda:0', dtype=torch.float64)

方法二

通过numpy创建的另外一种方法是:

使用 torch.from_numpy(ndarray)

这种方法只需要接受一个 ndarray 即可

arr = np.array([[1, 2, 3], [4, 5, 6]])
t = torch.from_numpy(arr)
print(arr)
print(t)

运行结果:

[[1 2 3] [4 5 6]] tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.int32)

注意

从torch.from_numpy 创建的 tensor 和 ndarray 共享内存,当修改其中一个的数据,另外一个也会被修改。

例如,在修改 array 的内容:

arr = np.array([[1, 2, 3], [4, 5, 6]])
t = torch.from_numpy(arr)

# 修改 array 的内容
arr[0,0] = 312
print(arr)
print(t)

运行结果:

[[312 2 3] [ 4 5 6]] tensor([[312, 2, 3], [ 4, 5, 6]], dtype=torch.int32)

再比如说,修改张量的内容:

arr = np.array([[1, 2, 3], [4, 5, 6]])
t = torch.from_numpy(arr)

# 修改 tensor 的内容
t[0,0] = -430
print(arr)
print(t)

运行结果:

[[-430 2 3] [ 4 5 6]] tensor([[-430, 2, 3], [ 4, 5, 6]], dtype=torch.int32)

创建全0张量

方法一

可以通过 torch.zeros() 创建全0张量

zeros(*size, out = None, dtype = None, layout = torch.strided, device = None, requires_grad = False)

其中,

  • size:为张量形状
  • out:输出的张量
  • dtype:数据类型
  • layout:内存中的布局形式,有strided,sparsed_coo等
  • device:所在设备,GPU/CPU
  • requires_grad:是否需要梯度,神经网路经常需要梯度
t1 = torch.tensor([1, 2, 3]) # 创建一个t1张量并赋初始值
t = torch.zeros((2,3), out = t1)
print(t, '\n', t1)
print(id(t), id(t1), id(t) == id(t1))

运行结果:

tensor([[0, 0, 0], [0, 0, 0]]) tensor([[0, 0, 0], [0, 0, 0]]) 2464000054400 2464000054400 True

通过上面显示的id发现,t和t1的id相同,所以t和t1在内存中指向的内存块相同。

方法二

可以通过torch.zeros_like() 创建全0张量:

torch.zeros(input, dtype = None, layout = None, device = None, requires_grad = False)

根据 input 形状创建全0张量

例如,创建一个 4*6 的全0张量

input = torch.empty(4, 6)
t = torch.zeros_like(input)
print(t)

运行结果:

tensor([[0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0.]])

创建全1张量

全1张量的创建和全0张量的创建方式基本一致,使用如下方式创建:

  • torch.ones()
  • torch.ones_like()

根据数值创建张量

方法一

  • torch.full()
torch.full(size, fill_value, out = None, dtype = None, layout = torch.strided, device = None, requires_grad = False)

其中新出现的参数:

  • fill_value:填充的值

例如,创建一个 2*2 的元素都是 8 的张量

t = torch.full((2, 2), 8 )
print(t)

运行结果:

tensor([[8, 8], [8, 8]])

方法二

torch.fuu_like()

torch.full_like(input, fill_value, out = None, dtype = None, layout = torch.strided, device = None, requires_grad = False)

例如,创建一个 4*3 的元素都为6的张量

input = torch.empty(4, 3)
t = torch.full_like(input, 6)
print(t)

运行结果:

tensor([[6., 6., 6.], [6., 6., 6.], [6., 6., 6.], [6., 6., 6.]])

创建等差的一维张量

可以通过 torch.arange() 创建等差的一维张量

arange(start = 0, end, step = 1, out = None, dtype = None, layout = torch.strided, device = None, requires_grad = False)

其中,

  • start:数列的起始值
  • end: 数列的结束值,取不到的,只能取到 end - 1
  • step:公差(步长),默认为1
t = torch.arange(1, 9, 2)
print(t)

运行结果:

tensor([1, 3, 5, 7])

创建等间距(均分)的一维张量

可以通过 torch.linspace() 来创建等间距均分张量

linspace(start, end, steps = 100, out = None, dtype = None, layout = torch.strided, device = None, requires_grad = False)

其中,

  • steps:创建出的一维张量中元素个数
  • end:结束位置可以取到
t = torch.linspace(1, 5, 4)
print(t)

运行结果:

tensor([1.0000, 2.3333, 3.6667, 5.0000])

注:linspace的图解

pytorch 随机张量 pytorch创建张量_pytorch 随机张量

创建对数均分的一维张量

可以通过 torch.logspace() 来创建对数均分张量

logspace(start, end, steps = 100, base = 10.0, out = None, dtype = None, layout = torch.strided, device = None, requires_grad = False)

其中参数,

  • base:对数函数的底,默认为10.0
t = torch.logspace(start = -5, end = 10, steps = 4)
print(t)

运行结果:

tensor([1.0000e-05, 1.0000e+00, 1.0000e+05, 1.0000e+10])

等间距均分 linspace 相当于 等差数列,对数均分 logspace 相当于 等比数列。对数均分相当于幂次的指数部分 成等间距均分。

t = torch.logspace(start = -2, end = 2, steps = 5, base = 2.0)
print(t)

tensor([0.2500, 0.5000, 1.0000, 2.0000, 4.0000])

注:logspace图解

pytorch 随机张量 pytorch创建张量_正态分布_02

创建单位对角矩阵(二维向量)

可以通过 torch.eye() 来创建单位对角矩阵。

torch.eye(n, m = None, out = None, dtype = None, layout = torch.strided, device = None, requires_grad = False)

其中,参数

  • m:矩阵行数
  • n:矩阵列数(默认为方阵)
t = torch.eye(4)
print(t)

运行结果:

tensor([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]])

创建正态分布(高斯分布)数据的张量

可以通过 torch.normal() 生成正态分布数据的张量

torch.noraml(mean, std, out = None)

其中,参数

  • mean:均值
  • std:标准差

这种正态分布的数据张量的创建方法可以分成4种方式:

(1) mean为张量,std为张量

(2) mean为标量,std为标量

(3) mean为标量,std为张量

(4) mean为张量,std为标量

(1)mean为张量,std为张量

# means为张量,std为张量
mean = torch.arange(1, 6, dtype = torch.float)
std = torch.arange(1, 6, dtype = torch.float)
t = torch.normal(mean, std)
print("mean:{}, std:{}".format(mean, std))
print(t)

运行结果:

mean:tensor([1., 2., 3., 4., 5.]), std:tensor([1., 2., 3., 4., 5.]) tensor([-0.9937, -0.4433, 5.5810, 6.5006, 0.1337])

此时,mean和std都是张量,可以理解为:

-0.9937是 mean = 1, std = 1 的正态分布采样得到,其他位置也是相应的正态分布采样得到,只是从不同的正态分布中采样罢了。

(2)mean为标量,std为标量

# mean为标量,std为标量
t = torch.normal(0.2, 1.0, size = (5, ))
print(t)

运行结果:

tensor([-0.6160, -0.6579, 0.5311, 0.2198, 0.4986])

这里生成的数据都是通过 mean = 0.2,std = 1.0 采样得到长度为5的一维张量。

(3) mean为标量,std为张量

# mean为标量,std为张量
mean = 2
std = torch.arange(1, 4, dtype = torch.float)
t = torch.normal(mean, std)
print("mean:{}, std:{}".format(mean, std))
print(t)

运行结果:

mean:2, std:tensor([1., 2., 3.]) tensor([ 1.2999, 2.6499, -3.2337])

1.2999是mean为2,std为1的正态分布采样得到,其他对应位置数据同理可得。只是从不同的正态分布中得到(均值相同,标准差不同)

(4)mean为张量,std为标量

# mean为张量,std为标量
mean = torch.arange(1, 4, dtype = torch.float)
std = 2
t = torch.normal(mean, std)
print("mean:{}, std:{}".format(mean, std))
print(t)

运行结果:

mean:tensor([1., 2., 3.]), std:2 tensor([-0.3166, 1.6594, 2.7413])

11.6594是mean为2,std为2的正态分布采样得到,其他对应位置数据同理可得。只是从不同的正态分布中得到(均值不同,标准差相同)

小结

(1) mean为张量,std为张量 —— 每次采样的正态分布均值不同,标准差也不同

(2) mean为标量,std为标量—— 每次采样的正态分布均值相同,标准差也相同

(3) mean为标量,std为张量—— 每次采样的正态分布均值相同,标准差不同

(4) mean为张量,std为标量—— 每次采样正态分布均值不同,标准差相同

创建标准正态分布数据的张量

一维标准正态分布

标准正态分布 pytorch 随机张量 pytorch创建张量_pytorch 随机张量_03

  • torch.randn()
torch.randn(*size, out = None, dtype = None, layout = torch.strided, device = None, requires_grad = False)

size :张量的形状

例如,创建一个长度为6的标准正态分布张量:

print(torch.randn(6))

运行结果:

tensor([-0.4437, 0.4294, 0.6771, -0.5297, -1.0764, -0.2395])

二维标准正态分布

print(torch.randn(3, 4))

运行结果:

tensor([[-0.2408, -0.3853, 0.8474, -1.4925], [ 0.4209, -0.2081, -0.7453, -0.4224], [ 0.0714, -0.6231, 0.2519, 1.3031]])

另一种办法

torch.randn_like() 可以根据张量的形状创建新的标准正态分布

randn_like(input, dtype = None, layout = None, device = None, requires_grad = False)
a = torch.ones((3,4))
t = torch.randn_like(a)
print(t)

运行结果:

tensor([[ 0.5477, -0.4851, 0.4772, -0.5393], [ 1.0461, 0.1628, 0.0659, 0.3142], [ 0.2300, 1.2297, 1.1029, -0.3967]])

创建在pytorch 随机张量 pytorch创建张量_正态分布_04上均匀分布的张量

一维均匀分布

  • torch.rand()
torch.rand(*size, out = None, layout = torch.strided, device = None, requires_grad = False)
print(torch.rand(5))

tensor([0.4322, 0.7985, 0.9677, 0.5745, 0.8513])

二维均匀分布

print(torch.rand(3, 4))

tensor([[0.4246, 0.3925, 0.1754, 0.7080], [0.9186, 0.9058, 0.8131, 0.6348], [0.7383, 0.6523, 0.8786, 0.9258]])

整数均匀分布

一维

在区间上创建整数均匀分布数据的张量:

torch.randint() 和 torch.randint_like()

torch.randint(low = 0, high, size, out = None, layout = torch.strided, device = None, requires_grad = False)

在区间 [low, high) 上生成整数均匀分布数据的张量

例如,创建在 [2,6) 上均匀分布的整数张量,长度为4的一维张量:

print(torch.randint(2, 6, (4, )))

运行结果:

tensor([5, 5, 5, 4])

二维

例如,创建在 [0,9) 上均匀分布的整数张量,二维张量:

print(torch.randint(9, (3, 4)))

运行结果:

tensor([[6, 4, 3, 2], [1, 8, 8, 4], [7, 8, 4, 0]])

创建随机排列一维向量 0~n-1

  • torch.randprem()
torch.randperm(n, out = None, dtype = torch.int64, layout = torch.strided, device = None, requires_grad = False)
print(torch.randperm(6))

运行结果:

tensor([4, 0, 1, 3, 5, 2])

创建伯努利分布的张量

torch.bernoulli:生成伯努利分布(0-1分布,两点分布)

torch.bernoulli(input, *, generator = None, out = None)

其中,

  • input:概率值

例如,先创建一个张量a,作为之后的概率值输入:

a = torch.empty(3, 3).uniform_(0, 1)
print(a)

运行结果:

tensor([[0.0085, 0.1244, 0.0287], [0.5544, 0.6066, 0.9340], [0.9562, 0.2950, 0.6683]])

然后通过a来创建张量t

t = torch.bernoulli(a) #使用上面创建的概率值a创建伯努利分布
print(t)

运行结果:

tensor([[0., 0., 1.], [1., 1., 1.], [1., 1., 0.]])