pytorch中的deepcopy pytorch中的数据类型_python
在PyTorch中,我们使用tensor来编码一个模型的输入和输出,以及模型的参数。

一、tensor的初始化

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

·data:data的数据类型可以是列表list、元组tuple、numpy数组ndarray、纯量scalar(又叫标量)和其他的一些数据类型。
·dtype:该参数可选参数,默认为None,如果不进行设置,生成的Tensor数据类型会拷贝data中传入的参数的数据类型,比如data中的数据类型为float,则默认会生成数据类型为torch.FloatTensor的Tensor。
·device:该参数可选参数,默认为None,如果不进行设置,会在当前的设备上为生成的Tensor分配内存。
·requires_grad:该参数为可选参数,默认为False,在为False的情况下,创建的Tensor不能进行梯度运算,改为True时,则可以计算梯度。
·pin_memory:该参数为可选参数,默认为False,如果设置为True,则在固定内存中分配当前Tensor,不过只适用于CPU中的Tensor。


设置require_grad参数的函数
Tensor.requires_grad_(requires_grad=True) → Tensor
Change if autograd should record operations on this tensor: sets this tensor’s requires_grad attribute in-place. Returns this tensor.

with torch.no_grad的作用

在该模块下,所有计算得出的tensor的requires_grad都自动设置为False,可以大大节省显存。
即使一个tensor(命名为x)的requires_grad = True,在with torch.no_grad中计算,由x得到的新tensor(命名为w)requires_grad也为False,且grad_fn也为None,即不会对w求导。例子如下所示:

x = torch.rand(10, 5, requires_grad = True)
y = torch.rand(10, 5, requires_grad = True)
with torch.no_grad():
    w = x + y
    print(w.requires_grad)
    print(w.grad_fn)
#False
#None


1、直接用数据初始化方式

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

2、由Numpy array转化而来

np_array=np.array(data)
x_np=torch.from_numpy(np_array)

t = torch.ones(5)
print(f"t: {t}")
n = t.numpy()#反之Numpy array也可以由tensor转化而来
print(f"n: {n}")
#t: tensor([1., 1., 1., 1., 1.])
#n: [1. 1. 1. 1. 1.]
t.add_(1)
print(f"t: {t}")
print(f"n: {n}")
#t: tensor([2., 2., 2., 2., 2.])
#n: [2. 2. 2. 2. 2.]
#CPU上的张量和NumPy数组可以共享它们的底层内存位置,所以改变一个的同时可以改变另一个。

3、由另一个tensor的shape转化而来

x_ones = torch.ones_like(x_data)
print(f"Ones Tensor: \n {x_ones} \n")

x_rand = torch.rand_like(x_data, dtype=torch.float)
print(f"Random Tensor: \n {x_rand} \n")
#Ones Tensor:
# tensor([[1, 1],
#        [1, 1]])

#Random Tensor:
# tensor([[0.5900, 0.9701],
#        [0.3483, 0.4137]])

4、用随机值或常量并借助shape元组定义tensor
torch.rand
torch.ones
torch.zeros
torch.empty
torch.empty()函数是PyTorch中的一个张量创建函数,用于创建一个未初始化的张量。它接受一个大小(shape)作为参数,并返回一个新的张量,其中元素的值是未定义的,故print出来看时是随机值。

shape = (2,3,)
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}")
#Random Tensor:
# tensor([[0.8330, 0.5998, 0.8980],
#        [0.6941, 0.3293, 0.7102]])
#
#Ones Tensor:
# tensor([[1., 1., 1.],
#        [1., 1., 1.]])
#
#Zeros Tensor:
# tensor([[0., 0., 0.],
#        [0., 0., 0.]])

5、torch.eye()
torch.eye(n)函数接受一个整数参数n,返回一个大小为(n, n)的二维张量(Tensor),表示一个n阶的单位矩阵。

import torch
# 创建一个3阶的单位矩阵
eye_matrix = torch.eye(3)
print(eye_matrix)

#输出结果为:
tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])


6、torch.as_tensor()、torch.tensor()、torch.Tensor()

torch.as_tensor(data, dtype=None, device=None)
该函数将给定的数据转换为Tensor对象。

data:输入的数据,可以是数字、列表、元组、NumPy数组等。
dtype(可选):所需的输出数据类型。如果未提供,则根据输入数据自动选择合适的数据类型。
device(可选):指定要在哪个设备上创建Tensor对象。默认情况下,使用当前设备。
返回值:一个新的Tensor对象,共享与输入数据相同的底层数据内存。

torch.Tensor(*size)
该构造函数创建一个未初始化的Tensor对象。

*size:Tensor对象的形状,以多个参数或一个元组的形式传入。
返回值:一个未初始化的Tensor对象,拥有指定的形状。

torch.tensor(data, dtype=None, device=None)
该构造函数根据给定的数据创建一个Tensor对象。

data:输入的数据,可以是数字、列表、元组、NumPy数组等。
dtype(可选):所需的输出数据类型。如果未提供,则根据输入数据自动选择合适的数据类型。
device(可选):指定要在哪个设备上创建Tensor对象。默认情况下,使用当前设备。
返回值:一个新的Tensor对象,包含了输入数据并根据需要进行数据类型转换。

这三个函数都用于创建Tensor对象,但有一些区别:

torch.as_tensor()尝试共享底层数据内存,不进行数据复制。
torch.Tensor()创建一个未初始化的Tensor对象,直接分配内存空间。
torch.tensor()根据输入数据创建一个新的Tensor对象,并根据需要进行数据类型转换。

data_list = [1, 2, 3]
tensor = torch.as_tensor(data_list)

shape = (2, 3)
tensor = torch.Tensor(shape)

data_array = np.array([4, 5, 6])
tensor = torch.tensor(data_array)


二、定义一个名为t的tensor后可以直接t.调用的属性和方法

属性
t = torch.rand(3,4)
print(f"Shape of tensor: {tensor.shape}")
print(f"Shape of tensor: {tensor.shape[0]}")
print(f"Shape of tensor: {tensor.shape[1]}")
print(f"Datatype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}")
print(tensor.requires_grad) #表示autograd时是否需要计算此tensor的梯度,默认False
print(tensor.grad) #存储梯度的值,初始为None
print(tensor.grad_fn) #反向传播时,用来计算梯度的函数
print(tensor.is_leaf) #该张量节点在计算图中是否为叶子节点
'''
当这个 tensor 是用户创建的时候,它是一个叶子节点,
当这个 tensor 是由其他运算操作产生的时候,它就不是一个叶子节点
'''
print(f"mean of tensor: {Tensor.mean(tensor)}")
print(f"variance of tensor: {Tensor.var(tensor)}")
#Shape of tensor: torch.Size([3, 4])
#Shape of tensor: 3
#Shape of tensor: 4
#Datatype of tensor: torch.float32
#Device tensor is stored on: cpu
#False
#None
#None
#True

requires_grad: 如果需要为张量计算梯度,则为True,否则为False。我们创建tensor时,可以指定requires_grad为True(默认为False)

grad_fn: grad_fn用来记录变量是怎么来的,方便计算梯度,y = x*3,y.grad_fn记录了y由x计算的过程。直接创建得到的叶子结点的grad_fn=None

grad:当执行完了backward()之后,通过x.grad查看x的梯度值。


方法

Tensor.reshape(*shape) → Tensor
Tensor.view(*shape) → Tensor,有时使用前要加contiguous()方法
Returns a new tensor with the same data as the self tensor but of a different shape.

x = torch.randn(4, 4)
x.size()#torch.Size([4, 4])
y = x.view(16)
y.size()#torch.Size([16])
z = x.view(-1, 8)  # the size -1 is inferred from other dimensions
z.size()#torch.Size([2, 8])


pytorch中的deepcopy pytorch中的数据类型_pytorch中的deepcopy_02

区别

view函数返回原始张量的一个视图。返回的张量将与原始张量共享数据。这意味着如果你改变原始张量,重塑后的张量也会改变。而且view函数要求张量数据在内存中是连续的。

reshape函数可以在数据存储不连续的情况下工作,返回原始张量的副本。

import torch
# 创建一个张量
x = torch.arange(10)
print('Original tensor:', x)
# 使用view改变形状
y = x.view(2, 5)
print('Reshaped tensor:', y)
# 改变原始张量
x[0] = 10
print('Original tensor after modification:', x)
print('Reshaped tensor after modification:', y)



import torch
# 创建一个张量
x = torch.arange(10)
print('Original tensor:', x)
# 使用reshape改变形状
y = x.reshape(2, 5)
print('Reshaped tensor:', y)
# 改变原始张量
x[0] = 10
print('Original tensor after modification:', x)
print('Reshaped tensor after modification:', y)
#在这个例子中,即使我们修改了原始张量,重塑后的张量也没有改变。


三、对tensor变量的操作(指通过torch.调用的方法)

1、tensor默认是在CPU上创建的,我们需要使用.to方法明确地将张量移动到GPU上(在检查GPU的可用性之后)
if torch.cuda.is_available():
    tensor = tensor.to("cuda")


2索引、切片、转置(permute、transpose)操作
tensor = torch.ones(4, 4)
print(f"First row: {tensor[0]}")
print(f"First column: {tensor[:, 0]}")
print(f"Last column: {tensor[..., -1]}")#此处用:或...都行
tensor[:,1] = 2
print(tensor)
#First row: tensor([1., 1., 1., 1.])
#First column: tensor([1., 1., 1., 1.])
#Last column: tensor([1., 1., 1., 1.])
#tensor([[1., 2., 1., 1.],
#        [1., 2., 1., 1.],
#        [1., 2., 1., 1.],
#        [1., 2., 1., 1.]])

'''
def transpose(self, dim0, dim1): -> Tensor
def permute(self, *dims): -> Tensor
transpose:只能选择tensor中两个维度进行转置
permute:可以让tensor按照任意指定维度顺序进行转置
'''
tensor1=tensor.transpose(0,1)#例原本坐标为(0,1,1,0)的点就会变成(1,0,1,0)
tensor2=tensor.permute(1,0,3,2)#例原本坐标为(0,1,1,0)的点就会变成(1,0,0,1)

注:但numpy中的def transpose(self, *axes):方法是让numpy.array()按照任意指定维度顺序进行转置


3、squeeze和unsqueeze操作,降维升维

pytorch中的deepcopy pytorch中的数据类型_pytorch中的deepcopy_03

Returns a new tensor with a dimension of size one inserted at the specified position.
The returned tensor shares the same underlying data with this tensor.
A dim value within the range [-input.dim() - 1, input.dim() + 1) can be used. Negative dim will correspond to unsqueeze() applied at dim = dim + input.dim() + 1.

>>> x = torch.tensor([1, 2, 3, 4])#shape为4
>>> torch.unsqueeze(x, 0)#shape变为1×4
tensor([[ 1,  2,  3,  4]])
>>> torch.unsqueeze(x, 1)#shape变为4×1
tensor([[ 1],
        [ 2],
        [ 3],
        [ 4]])

pytorch中的deepcopy pytorch中的数据类型_数据_04

Returns a tensor with all the dimensions of input of size removed.
For example, if input is of shape: pytorch中的deepcopy pytorch中的数据类型_pytorch中的deepcopy_05 then the out tensor will be of shape: pytorch中的deepcopy pytorch中的数据类型_pytorch_06
When dim is given, a squeeze operation is done only in the given dimension. If input is of shape: pytorch中的deepcopy pytorch中的数据类型_深度学习_07, squeeze(input, 0) leaves the tensor unchanged, but squeeze(input, 1) will squeeze the tensor to the shape pytorch中的deepcopy pytorch中的数据类型_python_08

>>> x = torch.zeros(2, 1, 2, 1, 2)
>>> x.size()
torch.Size([2, 1, 2, 1, 2])

>>> y = torch.squeeze(x)
>>> y.size()
torch.Size([2, 2, 2])

>>> y = torch.squeeze(x, 0)#leaves the tensor unchanged
>>> y.size()
torch.Size([2, 1, 2, 1, 2])

>>> y = torch.squeeze(x, 1)
>>> y.size()
torch.Size([2, 2, 1, 2])


4、算术操作torch.matmul,±*/

基础四则运算
a + b等同于torch.add()
a - b等同于torch.sub()
a * b等同于torch.mul()
a / b等同于torch.div()
直接进行加减乘除、开方torch.sqrt

a=10000**(torch.arange(0, 256, 2).float() / 256)

*法运算即mul,/法运算也类似也如下分类

(1)、Tensor*标量k的结果是Tensor的每个元素乘以k

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

(2)Tensor* 一维张量
Tensor* 行向量的结果是每列乘以行向量对应列的值
Tensor* 与列向量的结果是每行乘以列向量对应行的值

>>> a = torch.ones(3,4)
>>> a
tensor([[1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]])
>>> b = torch.Tensor([1,2,3,4])
>>> b
tensor([1., 2., 3., 4.])
>>> a * b
tensor([[1., 2., 3., 4.],
        [1., 2., 3., 4.],
        [1., 2., 3., 4.]])

>>> b = torch.Tensor([1,2,3]).reshape((3,1))
>>> b
tensor([[1.],
        [2.],
        [3.]])
>>> a * b
tensor([[1., 1., 1., 1.],
        [2., 2., 2., 2.],
        [3., 3., 3., 3.]])

(3)Tensor1* Tensor2
如果相乘的两个张量维度不一致,但Tensor2的维度与Tensor1的后几个维度对应相等就可以相乘。
相乘时会先将Tensor2以重复方式扩充为Tensor1的shape

当Tensor1、Tensor2维度相同时,对应维的值需要一样,如果对应维的值不一样,那其中必须有一个为1,否则会报错。

+法运算即add,-法运算也类似也如下分类
(1)(2)情况同上
(3)Tensor1+Tensor2
如果相加的两个张量维度不一致,但Tensor2的维度与Tensor1的后几个维度对应相等就可以相加。
相加时会先将Tensor2以重复方式扩充为Tensor1的shape

a = torch.ones([8, 4, 5, 6])
b = torch.ones([5, 6])
c = a+b
print(c.shape)#(8, 4, 5, 6)


当Tensor1、Tensor2维度相同时,对应轴的值需要一样,或者为1。

a = torch.ones([8, 4, 5, 6])
b = torch.ones([8, 1, 5, 6])
c = torch.ones([8, 2, 5, 6])
a+b可以。相加过程也是先将b重复扩充为与a相同shape
a+c报错

matmul运算

y1 = tensor @ tensor.T
y2 = tensor.matmul(tensor.T)#类似矩阵乘法

y3 = torch.rand_like(y1)
torch.matmul(tensor, tensor.T, out=y3)
#y1,y2,y3是相同的

z1 = tensor * tensor
z2 = tensor.mul(tensor)#两个tensor的对应位置相乘

z3 = torch.rand_like(tensor)
torch.mul(tensor, tensor, out=z3)
#z1,z2,z3是相同的
#tensor([[1., 4., 1., 1.],
#       [1., 4., 1., 1.],
#       [1., 4., 1., 1.],
#       [1., 4., 1., 1.]])


5、torch.reshape(input, shape) → Tensor

Parameters

  • input (Tensor) – the tensor to be reshaped
  • shape (tuple of python:ints) – the new shape
    A single dimension may be -1, in which case it’s inferred from the remaining dimensions and the number of elements in input.
    一个单一的维度可能是-1,在这种情况下,它是由其余的维度和输入的元素数量推断出来的。

应用举例:假设当我们的dataloader的batch_size设置为64。并且经过卷积(out_channels=6)之后,
我们需要使用tensorboard可视化,而彩色图片的writer.add.images(output)的彩色图片是in_channels=3的。
那么则需要对卷积后的图片进行reshape,Torch.size(64,6,30,30)---->torch.size(-1,3,30,30),-1的意思为最后自动计算其batch_size。
输出通道由6变成了3,从而每一个通道的数量增加,因而结果为torch.size(128,3,30,30)


注意如下两种reshape使用方式,这两个新的张量都是原始张量t的视图,也就是说,如果你修改了原始张量t的第一个元素,由于t1和t2都是t的视图,所以这个修改也会反映在t1和t2上。

import torch
# 创建一个张量
t = torch.rand(10)
# 使用reshape函数改变形状
t1 = torch.reshape(t, (2, 5))

# 使用reshape方法改变形状
t2 = t.reshape(2, 5)
t[0]=10
print(t1)
print(t2)


7、torch.cat、torch.split

torch.cat(tensors, dim=0, *, out=None) → Tensor
Concatenates the given sequence of seq tensors in the given dimension. All tensors must either have the same shape (except in the concatenating dimension) or be empty.

Parameters:
tensors (sequence of Tensors) – any python sequence of tensors of the same type. Non-empty tensors provided must have the same shape, except in the cat dimension.
dim (int, optional) – the dimension over which the tensors are concatenated
dim=-1表示倒数第一维

>>> x = torch.randn(2, 3)
>>> x
tensor([[ 0.6580, -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497]])
>>> torch.cat((x, x, x), 0)#shape是6×3
tensor([[ 0.6580, -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497],
        [ 0.6580, -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497],
        [ 0.6580, -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497]])
>>> torch.cat((x, x, x), 1)#shape是2×9
tensor([[ 0.6580, -1.0969, -0.4614,  0.6580, -1.0969, -0.4614,  0.6580,
         -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497, -0.1034, -0.5790,  0.1497, -0.1034,
         -0.5790,  0.1497]])


8、torch.clamp(input, min=None, max=None, *, out=None) → Tensor

Clamps all elements in input into the range [ min, max ]. Letting min_value and max_value be min and max, respectively, this returns:

pytorch中的deepcopy pytorch中的数据类型_数据_09
即把在min,max范围外的数限定为min或max,范围内的数不变

If min is None, there is no lower bound. Or, if max is None there is no upper bound.

>>> a = torch.randn(4)
>>> a
tensor([-1.7120,  0.1734, -0.0478, -0.0922])
>>> torch.clamp(a, min=-0.5, max=0.5)
tensor([-0.5000,  0.1734, -0.0478, -0.0922])

>>> min = torch.linspace(-1, 1, steps=4)
>>> torch.clamp(a, min=min)
tensor([-1.0000,  0.1734,  0.3333,  1.0000])


9、torch.linspace(start, end, steps, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor

Creates a one-dimensional tensor of size steps whose values are evenly spaced from start to end, inclusive. That is, the value are:

pytorch中的deepcopy pytorch中的数据类型_pytorch中的deepcopy_10

>>> torch.linspace(3, 10, steps=5)
tensor([  3.0000,   4.7500,   6.5000,   8.2500,  10.0000])
>>> torch.linspace(-10, 10, steps=5)
tensor([-10.,  -5.,   0.,   5.,  10.])
>>> torch.linspace(start=-10, end=10, steps=5)
tensor([-10.,  -5.,   0.,   5.,  10.])
>>> torch.linspace(start=-10, end=10, steps=1)
tensor([-10.])


10、repeat和expand

*Tensor.repeat(sizes) → Tensor
Repeats this tensor along the specified dimensions.

>>> x = torch.tensor([1, 2, 3])
>>> x.repeat(4, 2)#把x看作1×3了,然后1乘4,3乘2
tensor([[ 1,  2,  3,  1,  2,  3],
        [ 1,  2,  3,  1,  2,  3],
        [ 1,  2,  3,  1,  2,  3],
        [ 1,  2,  3,  1,  2,  3]])
>>> x.repeat(4, 2, 1).size()#把x看作1×1×3了,然后1乘4,1乘2,3乘1
torch.Size([4, 2, 3])

*Tensor.expand(sizes) → Tensor
Returns a new view of the self tensor with singleton dimensions expanded to a larger size.
Passing -1 as the size for a dimension means not changing the size of that dimension.

Tensor can be also expanded to a larger number of dimensions, and the new ones will be appended at the front. For the new dimensions, the size cannot be set to -1.

>>> x = torch.tensor([[1], [2], [3]])
>>> x.size()
torch.Size([3, 1])
>>> x.expand(3, 4)
tensor([[ 1,  1,  1,  1],
        [ 2,  2,  2,  2],
        [ 3,  3,  3,  3]])
>>> x.expand(-1, 4)   # -1 means not changing the size of that dimension
tensor([[ 1,  1,  1,  1],
        [ 2,  2,  2,  2],
        [ 3,  3,  3,  3]])


11、torch.sum(input, dim, keepdim=False, *, dtype=None)

Returns the sum of each row of the input tensor in the given dimension dim. If dim is a list of dimensions, reduce over all of them.
Parameters:
·input (Tensor) – the input tensor.
·dim (int or tuple of ints, optional) – the dimension or dimensions to reduce. If None, all dimensions are reduced.
·keepdim (bool) – whether the output tensor has dim retained or not.

Keyword Arguments:
·dtype (torch.dtype, optional) – the desired data type of returned tensor. If specified, the input tensor is casted to dtype before the operation is performed. This is useful for preventing data type overflows. Default: None.

>>>a=torch.arange(3*2*2).view(2,2,3)
>>>print(a)
tensor([[[ 0,  1,  2],
         [ 3,  4,  5]],

        [[ 6,  7,  8],
         [ 9, 10, 11]]])
>>>b=torch.sum(a,(1,2))
>#把(0,0,0)、(0,0,1)、(0,0,2)、(0,1,0)、(0,1,1)、(0,1,2)的相加,以此类推
>>>print(b)
tensor([15, 51])

>>>c=torch.sum(a,0)#即把坐标为(0,0,0)和(1,0,0)的相加,以此类推
>>>print(c)
tensor([[ 6,  8, 10],
        [12, 14, 16]])


12、torch.cumprod
>>>a=torch.Tensor([[0.1,0.2],[0.3,0.4]])
>>>b=torch.cumprod(a,dim=0)#第0维所以就是坐标为(0,0)和(1,0)的进行相乘
tensor([[0.1000, 0.2000],
		[0.0300, 0.0800]])
>>>b=torch.cumprod(a,dim=1)
tensor([[0.1000, 0.0200],
		[0.3000, 0.1200]])
13、torch.flatten(n),从第n维往后的维度展平
agg = tensor.sum().item()
print(agg, type(agg))
tensor.add_(5)
#In-place operations:Operations that store the result into the operand are called in-place. 
They are denoted by a _ suffix.
14、torch.mean(input, dim=None, keepdim=False)

input:输入的张量。
dim:指定要沿着哪个维度计算平均值。如果不指定该参数,则计算整个张量的平均值。可以传递一个整数或一个元组来指定多个维度。默认值为None。
keepdim:指定是否保持输出张量的维度与输入张量相同。如果设置为True,则输出张量将保留指定的维度。默认值为False。