1.PyTorch介绍与张量操作

#! https://zhuanlan.zhihu.com/p/542793773

1.PyTorch介绍与张量操作

之前一直没有时间好好总结pytorch的用法,这里利用假期时间总结一下,形成系统化记忆。

张量Tensors

Tensors和NumPy的多维数组ndarrays很像,它们可以共享内存,张量还支持在GPU上运行,并可以自动微分,首先引入torch:

import torch
import numpy as np

创建张量

1.从列表中创建张量:

data = [[1.,2],[3,4]]
x_data = torch.tensor(data)
x_data.dtype

out:torch.float32

知识点:

  • type()
    • 返回数据结构类型(list、dict、numpy.ndarray 等).
  • dtype()
    • 返回数据元素的数据类型(int、float等).
    • 备注:
      1. 由于 list、dict 等可以包含不同的数据类型,因此不可调用dtype()函数.
      2. np.array、torch.tensor中要求所有元素属于同一数据类型,因此可调用dtype()函数.
  • astype()
    • 改变np.array中所有数据元素的数据类型.
    • 备注:能用dtype() 才能用 astype().

2.从NumPy array中创建张量:

np_array= np.random.normal((2,3))
x_np = torch.from_numpy(np_array)
x_np

out:torch.float64

'''
这里补充一下np.random.normal正态分布的使用方法:
np.random.normal(loc,scale,size)
loc:float 均值 默认0
scale:float 方差 默认1.0
size:生成数的个数 
实际上loc和scale都可以list或者tuple的形式传入,如果传入list有两个数,在不指定生成个数的情况下,默认生成两个数,代表在不同均值的高斯分布下生成的情况
这里每行表示在均值2.0,方差3.0和均值3.0方差3.0的情况下各自生成的两个随机数;
注意size列向量个数必须等于传入的list的数的个数。
'''

np_random = np.random.normal((2.0,3.0),(3.0,3.0),(4,2))
np_random
c=torch.ones_like(x_np)

3.其他方式创建张量:

  • torch.ones_like(x_np)
  • torch.zeros_like(x_np)
  • torch.rand_like(x_np)

可以直接通过形状创建tensor

shape = (2,3,)#这里list和tuple都可以,最后一个逗号可有可无
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}\n")

张量操作

张量基本操作

a = torch.rand([2,2,])
a.dtype
a.shape
a.device

张量有100多种操作,tensor默认在cpu上创建,可以通过to操作移动到gpu上,然而对于一个大张量来说,将其从cpu上复制到gpu上很耗时间和内存。

if torch.cuda.is_available():
    tensor = tensor.to('cuda')
判断张量类型和生成张量常用操作:
'''
1.判断是否是一个张量,内部操作即isinstance(obj,Tensor)
'''
torch.is_tensor(a) 

'''
2.判断是否是一个复数类型,在torch中支持torch.complex64和torch.complex128
'''
torch.is_complex(a)

'''
3.判断是否是浮点型
'''
torch.is_floating_point(a)

'''
4.判断输入是否是单一的张量且不等于0
'''
torch.is_nonzero(a)

'''
5.返回输入张量中所有元素的数目
'''
torch.numel(a)

'''
6.这里以生成全0张量说明传入参数
torch.zeros(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor
这里dtype等默认为None时,是通过torch.set_default_tensor_type进行全局定义从而初始化的
'''
torch.zeros([5,5,],dtype = int32)

'''
7.训练时对于一个epoch进行遍历,用range、arange来生成一组连续的索引
torch.arange(start=0, end, step=1, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor
从形参可以看出,如果只传入一个参数,那么代表的是end的值
返回一个一维张量,(end-start)\step
'''
torch.arange(0,5,2) #output:[0,2,4]

for i in torch.arange(10):
    print("epoch:",i)

'''
8.torch.range(start=0, end, step=1, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor
返回一个一维张量,维度(end-start)\step +1,将end作为闭区间考虑
这个函数由于和Python本身的range冲突,将被移除,一般来说使用arange即可
'''
torch.range(0,5,1) #output:[0,1,2,3,4,5]

'''
9.产生一个对角线为1其余元素全0的矩阵
torch.eye(n, m=None, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor
'''
torch.eye(5,4)

'''
10.empty作用就是初始化一块内存放着,里面数据不重要,根本不会用
'''
torch.empty((2,3), dtype=torch.int64)

'''
11.full作用就是创建全为某个数的矩阵
'''
torch.full((2,2),5, )

切片、索引、聚合、旋转常用操作:
'''
1.cat作用就是连接多个张量,除了被连接的维度以外其他维度形状必须一样
'''
a = torch.rand([2,2,])
b = torch.rand([2,3,])
torch.cat([a,b],dim = 1) #dim [2,5]

'''
2.chunk把一个张量分割成特定数目的张量,每个chunk都是一个输入张量的特殊视角。张量如果不能被整除,最后一个张量会显得比较小。
torch.chunk(input, chunks, dim=0) → List of Tensors
'''
a = torch.rand((3,2,))
b,c = torch.chunk(a,chunks = 2,dim = 0)
e,f = torch.chunk(a,chunks = 3,dim = 1)
b,c,e,f

'''
3.将Index矩阵中元素的索引对应的dim维索引值更换为该索引元素的值然后到原tensor中寻找
'''
t = torch.tensor([[1, 2], [3, 4]])
torch.gather(t, 0, torch.tensor([[0, 0], [1, 0]])) #[[1,2][3,2]]
torch.gather(t, dim = 1, torch.tensor([[0, 0], [1, 0]])) #[[1,1][4,3]]

'''
3.reshape将输入张量的维度改变,元素顺序不变
'''
a = torch.arange(4.)
torch.reshape(a,[2,2})
b = torch.tensor([[0,1],[2,3]])
torch.reshape.reshape(b,(-1,)) #out[0,1,2,3,]

'''
4.inplace版本在torch中一般加下划线
scatter_将张量 src 中的所有值写入 self 在索引张量中指定的索引处。
index的行列对应src的行列,如果index维数较小,则用0补全。
'''
src = torch.arange(1, 11).reshape((2, 5))
src
index = torch.tensor([[0, 1, 2, 0]])
torch.zeros(3, 5, dtype=src.dtype).scatter_(0, index, src)#tensor([[1, 0, 0, 4, 0],
                                                                  # [0, 2, 0, 0, 0],
                                                                  # [0, 0, 3, 0, 0]])
index = torch.tensor([[0, 1, 2], [0, 1, 4]])
torch.zeros(3, 5, dtype=src.dtype).scatter_(1, index, src)

torch.full((2, 4), 2.).scatter_(1, torch.tensor([[2], [3]]),
           1.23, reduce='multiply')
torch.full((2, 4), 2.).scatter_(1, torch.tensor([[2], [3]]),
           1.23, reduce='add')

'''
5.split函数将一个张量划分成n块,可以传入数字也可以传入列表
对比chunk,chunk只能均分,split可以作为上层替代品
'''
a = torch.arange(10).reshape(5,2)
a
torch.split(a, 2)
torch.split(a, [1,4])

'''
6.squeeze函数将维度为1的维度删除掉
Ax1xBxCx1xD -> AxBxCxD  
eg.全连接可能把某些维度映射到1,然后再用squeeze去掉
'''
b = torch.rand((3,2))
c = torch.reshape(b,[3,1,2])
torch.squeeze(c)
d = torch.reshape(b,[3,1,2,1,1])
torch.squeeze(d,dim =1).shape #out:[3,2,1,1] dim不能传入list,需多次操作

'''
7.stack函数将张量堆叠起来,所有张量维度必须一致,实现了维度的扩充
''' 
a = torch.rand((3,2))
b = torch.rand((3,2))
torch.stack([a,b]).shape #[2,3,2]
torch.stack([a,b],dim = 1).shape #[3,2,2]

'''
8.take函数将张量看作是一维的
torch.take(input, index) → Tensor
然后根据索引位置返回新的张量
''' 
src = torch.tensor([[4, 3, 5],
                    [6, 7, 8]])
torch.take(src, torch.tensor([0, 2, 5])) #out [4,5,8] 

'''
9.tile函数对张量不同位置的元素进行拷贝
torch.tile(input, dims) → Tensor
如果dims维度小于input维度比如,src维度(8,6,4,2),dims(2,2),
那么把dim当作(1,1,2,2)处理
''' 
x = torch.tensor([1, 2, 3])
x.tile((2,))
y = torch.tensor([[1, 2], [3, 4]])
torch.tile(y, (2, 2)) #先按行复制2份,再按列复制两份

'''
10.transpose函数对张量转置
torch.transpose(input, dim0, dim1) → Tensor
''' 
x = torch.randn(2, 3)
x 
torch.transpose(x, 0, 1)

'''
11.unbind按照给定的维度返回这个维度切片的元组
torch.unbind(input,dim = 0) → seq
''' 
torch.unbind(torch.tensor[[1,2,3],[4,5,6],[7,8,9]])

'''
12.unsqueeze在某个维度上增加一个维度
torch.unsqueeze(input,dim ) → Tensor
比方说时间序列建模时,batch = 1,维度时间x特征,但是RNN要求3d,可以在前面加1维
''' 
x = torch.tensor([1, 2, 3, 4])
torch.unsqueeze(x, 0)
torch.unsqueeze(x, 1)

'''
13.where判断语句
torch.where(condition, x, y) → Tensor
''' 
x = torch.randn(3, 2)
y = torch.ones(3, 2)
x
torch.where(x > 0, x, y)#大于0的部分为x,否则为y,每个位置上的元素逐一判断
x = torch.randn(2, 2, dtype=torch.double)
x
torch.where(x > 0, x, 0.)

随机采样常用操作:
'''
1.manual_seed 使用同一个种子会从同样的分布中(CPU上)初始化随机数,
保证模型可复现,当然一个真正的好的模型还是要保证在任意随机种子下都work的
如果使用多个GPU,应该使用torch.cuda.manual_seed_all()为所有的GPU设置种子。
注意代码使用numpy时,还要调用numpy种子的设置np.random.seed()
'''
if args.seed is not None:
  random.seed(args.seed) #保证random方法生成随机数一致
  torch.manual_seed(args.seed) #为CPU设置种子用于生成随机数,以使得结果是确定的
   torch.cuda.manual_seed(args.seed) #为当前GPU设置随机种子;
   cudnn.deterministic = True

'''
2.bernulli,给定一个概率返回伯努利分布的tensor,每个位置是0或1
torch.bernoulli(input, *, generator=None, out=None) → Tensor
'''
a = torch.empty(3, 3).uniform_(0, 1)  # generate a uniform random matrix with range [0, 1]
a
torch.bernoulli(a) #每个位置都是伯努利分布的概率
a = torch.ones(3, 3) # probability of drawing "1" is 1
torch.bernoulli(a)
a = torch.zeros(3, 3) # probability of drawing "1" is 0
torch.bernoulli(a)

'''
3.normal返回正态分布
torch.normal(mean, std, *, generator=None, out=None) → Tensor
'''
#1.均值和方差长度一样
torch.normal(mean=torch.arange(1., 11.), std=torch.arange(1, 0, -0.1))
#2.共享均值,方差不同
torch.normal(mean=0.5, std=torch.arange(1., 6.))
#3.共享均值,方差
torch.normal(2, 3, size=(1, 4))

'''
4.随机数
rand [0,1)均匀分布 rand_like(tensor)
randint (low = 0,high,size) rand(3,10,(2,2))
randn 均值为0,方差为1正态分布 torh.randn(2,3)
randperm 随机组合,构建数据集常用
'''
torch.randperm(4) #tensor([2,1,0,3])

张量属性

pytorch中所有的tensor类型
浮点数类型通过IEEE754标准进行表示,复习一下计组知识,这里不做介绍

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值