pytorch中深度拷贝_Pytorch深度指南-torch与Tensor常用操作方法

pytorch深度指南-torch与Tensor常用操作方法

import torch

torch.Tensor会继承某些torch的某些数学运算,例如sort, min/max....不需要调用相应的torch.funciton进行处理,下文中如果是torch/Tensor即表示该函数可以直接对self的tensor使用,也可以使用torch给的相应函数接口

torch/Tensor.reshape(input, shape) → Tensor

指定tensor新的shape,reshape过后不会更该数据量和数据格式,只是对数据的shape做了调整,因此要保证reshape前后元素个数一致。 参数:

input(tensor) - 输入tensor

shape(tuple or *size) - 新的shape 如果还剩下一个维度,很好,你可以直接使用-1来替代,表示这个维度中应该有的元素数量

torch/Tensor.view()

与reshape功能类似,将源tensor的shape改变指定形状。

原文中这样描述 Returned tensor will be a view of input. Otherwise, it will be a copy. Contiguous inputs and inputs with compatible strides can be reshaped without copying, but you should not depend on the copying vs. viewing behavior.二者区别:当tensor都为contiguous类型(邻近模式)时,两个函数并无差异,使用原来的数据内容,不会复制一份新的出来;如果tensor不是,例如经过了transpose或permute之后,需要contiguous然后再使用view。reshape其实就是.contiguous+view,这样不会开辟新的空间存放tensor,而是共享原来的数据内存。

torch.arange(10).reshape((2,5))

tensor([[ 0., 1., 2., 3., 4.],

[ 5., 6., 7., 8., 9.]])

torch.arange(10).reshape(5, -1)#可以看到新的shape是(5,2),使用-1自动求剩余最后一个维度

tensor([[ 0., 1.],

[ 2., 3.],

[ 4., 5.],

[ 6., 7.],

[ 8., 9.]])

torch.index_select(input, dim, index, out=None)

指定在哪个轴上,index是多少,注意index要是一个tensor, dim和index确定了一个维度的坐标$(dim_1=index_i,....dim_n=index)$

a = torch.randn([3,4])

print(a)

a.index_select(0,torch.tensor([2])).reshape(2,2)#

tensor([[ 0.0334, 0.9123, -1.2300, -0.9336],

[-0.8364, 0.6584, 0.6878, -2.5896],

[ 0.1862, -0.3752, 0.4150, -1.4008]])

tensor([[ 0.1862, -0.3752],

[ 0.4150, -1.4008]])

torch.linespace(start, end, steps=100, out=None)

返回一个一维tensor,包含step个元素,每个元素之间等间距,依次递增$\frac{end-start}{step}$

torch.linspace(0,1,10, dtype=torch.float32)

tensor([ 0.0000, 0.1111, 0.2222, 0.3333, 0.4444, 0.5556, 0.6667,

0.7778, 0.8889, 1.0000])

Tensor.repeat(input, *size)

把输入的input当做一个基本模块m,扩张成size的tensor,其中每个元素为m,最后返回的Tensor的shape为() *size必须比input的维度要高,

if input和size维度相等:

input = (a,b)

*size = (c,d)

out = (a×c, b×d)

size > input

input = (a,b)

*size = (c,d,e)

out = (c, d×a,e×b)

torch.Tensor.repeat(torch.tensor([2,3]),2,4,3).shape

torch.Size([2, 4, 6])

torch/Tensor.nonzero()

返回一个包含输入input中非零元素索引的张量,输出张量中非零元素的索引 若输入input有n维,则输出的索引张量output形状为z * n, 这里z是输入张量input中所有非零元素的个数

a = torch.eye(3,3)

print('a:', a)

a.nonzero()#所有非0的坐标,注意返回的每个元素都是一个完整的坐标index~

a: tensor([[ 1., 0., 0.],

[ 0., 1., 0.],

[ 0., 0., 1.]])

tensor([[ 0, 0],

[ 1, 1],

[ 2, 2]])

b = torch.arange(8).reshape(2,2,2)

print('b:', b)

b.nonzero()#z=7,n=3,输出(7*3)矩阵

b: tensor([[[ 0., 1.],

[ 2., 3.]],

[[ 4., 5.],

[ 6., 7.]]])

tensor([[ 0, 0, 1],

[ 0, 1, 0],

[ 0, 1, 1],

[ 1, 0, 0],

[ 1, 0, 1],

[ 1, 1, 0],

[ 1, 1, 1]])

torch/Tensor.chunk(tensor, chunks, dim=0)

将一个tensor在指定维度上分成chunks个数据块,为cat的逆过程,最后一个块可能会小一些,返回的是一个元组,每个元素都是其中一块 参数: tensor (Tensor) – 输入Tensor chunks (int) – 分成几块的数量 dim (int) – 沿着哪个维度进行切分可以看成torch.cat()的逆运算过程

c = torch.randn(7,4)

c.chunk(chunks=4,dim=0)#,在dim=0上划分,返回的是一个元组,共分为4块

(tensor([[ 0.0722, 0.2573, -0.2504, 1.7426],

[-3.3098, 0.8971, 0.0274, -0.2365]]),

tensor([[ 1.1137, 0.3401, -1.4004, 1.2823],

[-0.5553, 0.8056, -0.1764, 0.7666]]),

tensor([[ 1.3739, -1.4938, 1.8446, 0.4783],

[-1.5898, -0.2520, -0.4873, 1.6098]]),

tensor([[ 0.5421, -0.2846, 0.1441, -0.5456]]))

torch/Tensor.clamp(input, min, max, out=None)

功能:将tensor所有元素裁剪到指定范围[min, max]并返回

c = torch.tensor([1,2,3,4,5,6,7,8])

c = c.clamp(3,6)#裁剪并返回

c

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

torch/Tensor.sort(input, dim=None, descending=False, out=None)

沿着指定维度排序,如果没有指定维度,默认最后一个维度,descending选择升序还是降序,返回一个元组(排序好的tensor和相应的索引)

a = torch.randint(0,10,(2,6)).squeeze().int()

a

tensor([[ 0, 9, 7, 6, 3, 0],

[ 8, 1, 8, 3, 6, 4]], dtype=torch.int32)

a.sort(dim=0)#返回排序好的值和索引

(tensor([[ 0, 1, 7, 3, 3, 0],

[ 8, 9, 8, 6, 6, 4]], dtype=torch.int32),

tensor([[ 0, 1, 0, 1, 0, 0],

[ 1, 0, 1, 0, 1, 1]]))

torch/Tensor.topk(input, k, dim=None, largest=True, sorted=True, out=None) -> (Tensor, LongTensor)

返回在指定维度上k个最大的元素,默认最后一个维度,返回值是一个元组包括值和索引(values, indices) 参数:

input (Tensor) – 输入tensor

k (int) – k个最值元素

dim (int) – 沿着哪个维度排许

largest (bool) – 选取最大元素还是最小元素

sorted (bool) – 返回元素是否有序

torch.randn(12).topk(4)#返回topK数值和位置索引

(tensor([ 2.0778, 1.6199, 0.8411, 0.2411]), tensor([ 0, 1, 9, 4]))

torch.split(tensor, split_size_or_sections, dim=0)

torch/Tensor.flatten(input, start_dim=0, end_dim=-1) → Tensor

将一个tensor按照存储位置顺序展平

a = torch.randn(3,3)

print(a)

# torch.flatten(a)

# a.flatten()

tensor([[-1.6724, -0.0280, 0.0100],

[ 0.3437, 0.9472, -0.3655],

[-0.3134, -2.6223, -0.7097]])

torch.numel()

返回tensor包含所有元素的数量

torch.stack(seq, dim=0, out=None) → Tensor

在一个新的维度上,拼接原有的tensor,注意该操作会产生新的维度,待组合的tensor要有相同的size

参数:

seq (sequence of Tensors) – 待拼接的tensor,要以seq形式

dim (int) – dimension to insert. Has to be between 0 and the number of dimensions of concatenated tensors (inclusive)

torch/Tensor.squeeze(input, dim=None, out=None) → Tensor

去除tensor中维度=1所在的那个维度,很多时候,为了保持tensor的shape对齐会提升维度,提升一些无关紧要的1维,然而在使用的时候我们不希望这些无关紧要的维度干扰我们的操作。

例如,如果输出shape:(A×1×B×1×D),经过squeeze后(A×B×D)注意:返回的tensor与输入共享存储空间,改变其中任何一个都会改变相应其他那个

a = torch.arange(10).reshape(1,1,2,5)

print('a:', a)

b = a.squeeze()

b += 2

a#可以看到虽然对b操作,但是原始a的值也发生了变化

a: tensor([[[[ 0., 1., 2., 3., 4.],

[ 5., 6., 7., 8., 9.]]]])

tensor([[[[ 2., 3., 4., 5., 6.],

[ 7., 8., 9., 10., 11.]]]])

torch/Tensor.unsqueeze(dim)

提升一个新的维度,该dim=1,例如:(2,6)->(1,2,6)

torch.transpose(input, dim0, dim1) → Tensor

轴/坐标索引 交换

torch.where(condition, x, y) → Tensor

逐个位置元素判断,返回一个tensor可能来自源数据x或者y。

**注意:**

条件,x,y都必须是可广播的

**参数:**

condition (ByteTensor) – When True (nonzero), yield x, otherwise yield y

x (Tensor) – values selected at indices where condition is True

y (Tensor) – values selected at indices where condition is False

Returns:

返回的tensor的shape与条件,x和y都是一致的!!)

x = torch.randn(3,2)

y = torch.ones(3,2)

print('x:', x)

print('y', y)

torch.where(x > 0 , x, y)

x: tensor([[ 0.8968, 3.3511],

[-0.8421, -1.1878],

[-0.0903, 0.6168]])

y tensor([[ 1., 1.],

[ 1., 1.],

[ 1., 1.]])

tensor([[ 0.8968, 3.3511],

[ 1.0000, 1.0000],

[ 1.0000, 0.6168]])

Tensor.type(torch.type)tensor数据类型转换

Tensor.int()将数据转为int

Tensor.long()将数据转为longInt

Tensor.byte()将数据转换为无符号整型

Tensor.float()将数据转换为float类型

Tensor.double()将数据转换为double类型

a = torch.tensor([1,2,3,4])

a.long().type()

torch.LongTensor

a.float().type()

torch.FloatTensor

a.byte().type()

torch.ByteTensor

Tensor.cuda(device, non_blocking=False)

Returns a copy of this object in CUDA memory. 返回一个CUDA内存数据的副本,将输入数据存入cuda

a = torch.arange(1200, dtype=torch.float64).cuda()

Tensor.clone()

Returns a copy of the self tensor. The copy has the same size and data type as self. 返回selftensor的一个拷贝,与原数据有相同的size和数据类型clone()得到的Tensor不仅拷贝了原始的value,而且会计算梯度传播信息,copy_()只拷贝数值

a = torch.tensor([1,2,3,4,5], dtype=torch.float32, requires_grad=True)

b = a.clone()#a经过克隆得到b,

c = (b ** 2).mean()#

c.backward()

print('a_grad:', a.grad)#但是梯度传播没有因此中断

a_grad: tensor([ 0.4000, 0.8000, 1.2000, 1.6000, 2.0000])

Tensor.copy_(src, non_blocking=False)

只拷贝src的数据到selftensor,并返回self,src和self可以有不同的数据类型和不同的设备上.

参数: src (Tensor) – 源数据 non_blocking (bool) – 如果是True,copy操作跨CPU和GPU,但可能会出现异步问题

a = torch.tensor([1,2,3,4,5], dtype=torch.float32, requires_grad=True)

b = (a ** 2).mean()

b.backward()

print('a_grad:', a.grad)

c = torch.zeros(5)

c.copy_(a)

print('c_grad:', c.grad)

a_grad: tensor([ 0.4000, 0.8000, 1.2000, 1.6000, 2.0000])

c_grad: None

Tensor.contiguous()

将tensor改为连续存储模式

Tensor.fill_()内容填充

tensor内部全部填充value元素

Tensor.zero_()

tensor内容全部填充0

Tensor.normal_(mean, std, out=None)

a = torch.randn(3,3)

a.fill_(3)#指定内容填充

tensor([[ 3., 3., 3.],

[ 3., 3., 3.],

[ 3., 3., 3.]])

a.zero_()

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

[ 0., 0., 0.],

[ 0., 0., 0.]])

a.normal_()

tensor([[ 0.1044, -0.1353, -0.7540],

[-0.6852, 0.2683, 0.8297],

[ 2.8920, 0.2846, -1.1742]])

torch生成常用矩阵

torch.zeros(*size)

生成全零矩阵

torch.ones(*size)

生成全1矩阵

torch.eye(*size)

生成对角矩阵,对角线元素全为1

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

返回指定区间,指定步长的1-D tensor

torch.zeros(3,3)

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

[ 0., 0., 0.],

[ 0., 0., 0.]])

torch.ones(3,3)

tensor([[ 1., 1., 1.],

[ 1., 1., 1.],

[ 1., 1., 1.]])

torch.eye(3,3)

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

[ 0., 1., 0.],

[ 0., 0., 1.]])

torch.arange(0, 10, 2)#区间是左壁右开,不包含end

tensor([ 0., 2., 4., 6., 8.])

torch/Tensor.round(input, out=None) → Tensor

对tensor内所有元素取整

a = torch.randint(0,10,(2,2))

a.round()

tensor([[ 7., 5.],

[ 1., 5.]])

torch.randomtorch自带随机模块

生成随机数的功能模块

torch.random.manual_seed(seed)

设置随机数种子

torch.randint(low, high, size)

返回一个服从uniform分布的int随机矩阵

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

$\text{out}_{i} \sim \mathcal{N}(0, 1)$ 生成一个服从(0,1)标准正态分布的矩阵,传入size使用参数收集机制。

torch.randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False) → LongTensor

生成一个0→n-1随机序列 参数:

n (int) – 生成序列最大上界(不包含n)

torch.randint(0, 10, (2,2))#使用参数收集机制

tensor([[ 6., 9.],

[ 3., 8.]])

torch.randn(2,2)#使用参数收集机制,服从搞死分布

tensor([[-0.7565, 1.2032],

[-0.7030, 1.7259]])

torch.randperm(4)#返回一个生成的序列

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

torch.arange(0,10,1).type(torch.int32)

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

你可能感兴趣的:(pytorch中深度拷贝)