欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

pytorch 学习之 Tensor 基础

程序员文章站 2022-06-12 10:05:35
...

tensor作为pytorch的基本操作对象,是首先要了解的。

一、tensor的8个属性:

# 数据相关
t.data		# tensor的数据
t.dtype		# tensor的数据类型
t.shape		# tensor的形状
t.device	# tensor所在的设备

# 梯度相关
t.grad			# data的梯度
t.grad_fn		# 创建tensor的function
t.requires_grad	# 是否需要求导
t.is_leaf		# 是否是叶子结点

二、tensor的创建:

1. 直接创建

t = torch.tensor([[0, 5, 4, 5, 8, 9], [2, 7, 5, 8, 8, 6]])

2. 从ndarray创建(ndarray转tensor)

# 创建的tensor和原来的ndarray共享内存
arr = np.array([[1, 3, 3], [4, 5, 6]])
t = torch.from_numpy(arr)

3. 创建全0张量(可用于对张量初始化)

# 创建3*3的全0张量
t = torch.zeros((3, 3))
# 按照input的形状创建全0张量
t1 = torch.zeros_like(input)

4. 创建全1张量

# 创建3*3的全1张量
t = torch.ones((3, 3))
# 按照input的形状创建全1张量
t1 = torch.ones_like(input)

5. 创建自定义全值张量

# 创建3*3的全5张量,需是float,int会报warning
t = torch.full((3, 3), 5.)
# 按照input的形状创建全6张量
t1 = torch.full_like(input, 6)

6. 创建等差1维张量

# 步长为2的等差数列1维张量,范围[0,10)
t = torch.arange(0, 10, 2)

7. 创建均分1维张量

# 创建均分1维张量,范围[0,10],长度默认100
t = torch.linspace(0, 10)
# 创建均分1维张量,范围[0,10],长度5
t1 = torch.linspace(0, 10, steps=5)

---------------------- output ----------------------
tensor([ 0.0000,  0.1010,  0.2020,  0.3030,  0.4040,  0.5051,  0.6061,  0.7071,
         0.8081,  0.9091,  1.0101,  1.1111,  1.2121,  1.3131,  1.4141,  1.5152,
         1.6162,  1.7172,  1.8182,  1.9192,  2.0202,  2.1212,  2.2222,  2.3232,
         2.4242,  2.5253,  2.6263,  2.7273,  2.8283,  2.9293,  3.0303,  3.1313,
         3.2323,  3.3333,  3.4343,  3.5354,  3.6364,  3.7374,  3.8384,  3.9394,
         4.0404,  4.1414,  4.2424,  4.3434,  4.4444,  4.5455,  4.6465,  4.7475,
         4.8485,  4.9495,  5.0505,  5.1515,  5.2525,  5.3535,  5.4545,  5.5556,
         5.6566,  5.7576,  5.8586,  5.9596,  6.0606,  6.1616,  6.2626,  6.3636,
         6.4646,  6.5657,  6.6667,  6.7677,  6.8687,  6.9697,  7.0707,  7.1717,
         7.2727,  7.3737,  7.4747,  7.5758,  7.6768,  7.7778,  7.8788,  7.9798,
         8.0808,  8.1818,  8.2828,  8.3838,  8.4848,  8.5859,  8.6869,  8.7879,
         8.8889,  8.9899,  9.0909,  9.1919,  9.2929,  9.3939,  9.4949,  9.5960,
         9.6970,  9.7980,  9.8990, 10.0000])
tensor([ 0.0000,  2.5000,  5.0000,  7.5000, 10.0000])

8. 创建对数均分1维张量

# 创建对数均分1维张量,范围[0,10],长度默认100,底默认10
# 在区间 base^(start)和 base^(end) 上按照 [start,end] 均分的 steps 个点
t = torch.logspace(0, 4, steps=2, base=2)

---------------------- output ----------------------
tensor([1., 16.])

9. 创建单位对角阵张量

t = torch.eye(3)
t = torch.eye(2, 3)

依概率分布创建张量

10. 正态分布(高斯分布)

# mean:张量 std:张量
# 此时mean和std维数(n)要相等,由他们生成n个正态分布,
# 从每个分布随机抽取一个数,组成一个1维张量
mean = torch.arange(1, 5, dtype=torch.float)
std = torch.arange(1, 5, dtype=torch.float)
t_normal = torch.normal(mean, std)
print(t_normal)
---------------------- output ----------------------
tensor([1.2151, 1.2076, 3.8062, 9.3667])
-------------------- end output --------------------

# mean:标量 std:标量
# 生成1个分布,随机取size大小的数
# 1维
t_normal = torch.normal(0, 1, size=(4,))
# 4*2维
t_normal1 = torch.normal(0, 1, size=(4, 2))
print(t_normal)
print(t_normal1)
---------------------- output ----------------------
tensor([0.2177, 0.1591, 1.2840, 0.8412])
tensor([[ 0.9582,  1.6487],
        [-1.0021,  2.0398],
        [ 0.2099,  0.9041],
        [ 2.0284, -0.2725]])
-------------------- end output --------------------

# mean:张量 std:标量
# 生成同mean大小个分布,所有分布的std相同
# 从每个分布随机抽取一个数,组成一个1维张量
# mean:标量 std:张量 同理
mean = torch.arange(1, 5, dtype=torch.float)
# 1维
t_normal = torch.normal(mean, 1)
print(t_normal)
---------------------- output ----------------------
tensor([ 1.0105, -0.4155,  3.2346,  2.8099])
-------------------- end output --------------------

11. 标准正态分布(mean=0, std=1)

# 由于均值和标准差都确定了,所以只需size就可以创建
t_normal = torch.randn(2, 3)

12. 均匀分布

# 默认在区间[0,1)上,生成标准均匀分布
# 以下两个是等效的
# 生成2*3的tensor
t_normal = torch.rand(2, 3)
t_normal1 = torch.rand(size=(2, 3))
# torch.rand_like()

# 在区间[low,high)上,生成整数均匀分布
t_normal_int = torch.randint(2, 13, size=(5,))
# output: tensor([4, 3, 9, 5, 5])
# torch.randint_like()

13. 创建0到n-1的整数随机排列

# 常用来生成乱序索引
# 返回1维张量
t_normal = torch.randperm(5)

---------------------- output ----------------------
tensor([1, 4, 2, 3, 0])

14. 伯努利分布/0-1分布/两点分布

input = torch.rand(1, 6)
t_normal = torch.bernoulli(input)
# p 为概率,此时input的概率作用失效
t_normal1 = torch.bernoulli(input, p=0)

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

三、tensor的操作方法:

拼接

1. 将tensor按维度进行拼接 torch.cat()
import torch

# torch.cat(tensors, 	# 张量序列
#           dim=0,  	# 要拼接的维度
#           out=None)
t = torch.ones((2, 3))
t_0 = torch.cat([t, t], dim=0)
t_1 = torch.cat([t, t], dim=1)

---------------------- output ----------------------
t:tensor([[1., 1., 1.],
        [1., 1., 1.]]) shape:torch.Size([2, 3])
t_0:tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]]) shape:torch.Size([4, 3])
t_1:tensor([[1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1.]]) shape:torch.Size([2, 6])

2. 在新创建的维度上进行拼接 torch.stack()

import torch

# torch.stack(tensors,	# 张量序列
#             dim=0,	# 要拼接的维度
#             out=None)
t = torch.ones((3, 4))
t_stack_0 = torch.stack([t, t], dim=0)
t_stack_1 = torch.stack([t, t], dim=2)

---------------------- output ----------------------
t:tensor([[1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]]) shape:torch.Size([3, 4])
t_stack_0: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.]]]) shape:torch.Size([2, 3, 4])
t_stack_1: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.]]]) shape:torch.Size([3, 4, 2])

分割

1. 将tensor按维度进行平均切分 torch.chunk()

# torch.chunk(input, 	# 要切分的张量
#             chunks, 	# 要切分的分数
#             dim=0) 	# 要切分的维度
# 返回张量列表
# 若不能整除,最后一份小于其他张量
a = torch.ones((2, 5))
list_of_tensors = torch.chunk(a, chunks=3, dim=1)
print(a)

for idx, t in enumerate(list_of_tensors):
print("第{}个张量:{},shape is {}".format(idx + 1, t, t.shape))

---------------------- output ----------------------
tensor([[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]])1个张量:tensor([[1., 1.],
        [1., 1.]]),shape is torch.Size([2, 2])2个张量:tensor([[1., 1.],
        [1., 1.]]),shape is torch.Size([2, 2])3个张量:tensor([[1.],
        [1.]]),shape is torch.Size([2, 1])

2. 将tensor按维度进行切分,可指定切分的长度 torch.split()

# torch.split(tensor,
#             split_size_or_sections, # 为int时,表示每一份的长度;为list时,按list元素切分
#             dim=0)

a = torch.ones((2, 5))
print(a)

# 为 int
# list_of_tensors = torch.split(a, 3, dim=1)
# 为 list, list各项和,需等于原tensor的长度,否则报错
list_of_tensors = torch.split(a, [1, 3, 1], dim=1)
for idx, t in enumerate(list_of_tensors):
	print("第{}个张量:{},shape is {}".format(idx + 1, t, t.shape))
	
---------------------- output ----------------------
tensor([[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]])1个张量:tensor([[1.],
        [1.]]),shape is torch.Size([2, 1])2个张量:tensor([[1., 1., 1.],
        [1., 1., 1.]]),shape is torch.Size([2, 3])3个张量:tensor([[1.],
        [1.]]),shape is torch.Size([2, 1])

索引

1. 根据 index

# torch.index_select(input,		# 要操作的tensor
#					dim,		# 要索引的维度
#					index,		# 索引,int或list
#					out=None)
					
a = torch.randint(0, 9, size=(3, 3))

# 按行索引,0行和2行
# index_select的index必须是long(int64)类型
inx = torch.tensor([0, 2], dtype=torch.long)

t_select = torch.index_select(a, dim=0, index=inx)
print("{}\n{}".format(a, t_select))

---------------------- output ----------------------
tensor([[8, 4, 5],
        [5, 3, 5],
        [5, 0, 7]])
tensor([[8, 4, 5],
        [5, 0, 7]])

2. 根据 mask

# torch.masked_select(input,
#                     mask, # 与input同形状的布尔类型张量
#                     out=None)
# 通常用来筛选数据,找出所有符合要求的项,返回1维张量

a = torch.randint(0, 9, size=(3, 3))
# 对a中数据进行判断,大于等于5为True
# ge means greater than or equal, gt:greater than. le lt
mask = a.ge(5)
t_select = torch.masked_select(a, mask)
print("a:{}\nmask:{}\nt_select:{}".format(a, mask, t_select))