这是我创建的编程算法竞赛学习小组频道,欢迎大家加入,共同进步!!!
一般来说,数据的操作包含获取数据和将数据读入计算机后对其进行处理,如果没有方法来存储数据,那么获取数据也是没有意义的,接下来,我们将学习PyTorch中的一些基础的数据操作。
在机器学习,深度学习中,一般都会使用n维数组,也称张量,进行各种计算操作,再学习数据操作之前我们先来了解一下张量的基本介绍。
张量是多维数组,在 PyTorch 中,它是一种类似于 numpy 数组的数据结构。它可以存储向量、矩阵、三维数组等多维数据。张量可以使用 GPU 进行加速计算,这使得 PyTorch 成为了一种非常强大的深度学习框架。 张量也是PyTorch的核心数据结构,他是用来存储和变换数据的,并且他能跟踪操作的历史记录,可以用来计算梯度。
在 PyTorch 中,可以使用 torch.Tensor() 或 torch.tensor() 函数来创建张量。
使用 torch.Tensor() 函数:
import torchtensor = torch.Tensor(2, 3)
print(tensor)
使用 torch.tensor() 函数:
import torchtensor = torch.tensor((2, 3))
print(tensor)
使用 torch.zeros() 函数创建全0张量:
import torch# 创建一个 2x3 的全零张量
tensor = torch.zeros((2, 3))
print(tensor)
使用 torch.ones() 函数创建全1张量:
import torch# 创建一个 2x3 的全1张量
tensor = torch.ones((2, 3))
print(tensor)
使用 torch.rand() 函数创建随机张量:
import torch# 创建一个 2x3 的全零张量
tensor = torch.rand((2, 3))
print(tensor)
在 PyTorch 中,可以使用 .shape 属性来访问张量的形状。
import torch# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)
print(tensor)# 访问张量的形状
print(tensor.shape)
tensor([[ 0.0012, -0.7267, 0.0413],[-0.2877, -0.6770, 0.6846]])
torch.Size([2, 3])
或者使用 .size() 函数来获取张量的形状
import torch# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)
print(tensor)# 访问张量的形状
print(tensor.size())
tensor([[ 0.1515, -0.9561, -1.0691],[-1.2747, 0.2559, 0.0547]])
torch.Size([2, 3])
.shape 和 .size() 都能得到一个torch.Size的对象,这是一个tuple, 它包含了张量的各维度的大小, 例如上面的代码中得到的是(2,3)
你也可以使用索引的方式来访问某一维的大小。
print(tensor.shape[0]) # 2
另外,还可以使用 .ndim 属性获取张量的维度数, 例如上面的代码中得到的是2。
print(tensor.ndim) # 2
张量的形状是一个重要的信息,在许多操作中都需要用到它。
在 PyTorch 中,可以使用 .view() 方法来改变一个张量的形状,而不改变元素数量和元素值。
import torch# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)
print(tensor)# 改变形状为 3x2
tensor = tensor.view(3, 2)
print(tensor)
tensor([[-0.9560, -1.4888, -0.1156],[-0.2095, -0.6208, -0.5531]])
tensor([[-0.9560, -1.4888],[-0.1156, -0.2095],[-0.6208, -0.5531]])
或者使用 -1 作为一维大小。
import torch# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)
print(tensor)# 改变形状为 3x2
tensor = tensor.view(-1, 2)
print(tensor)
tensor([[ 0.3850, 0.3420, -0.7406],[-0.0208, 0.9118, 1.3379]])
tensor([[ 0.3850, 0.3420],[-0.7406, -0.0208],[ 0.9118, 1.3379]])
在上面的例子中,我们将原始的 2x3 的张量改变成了 3x2 的张量,其中元素数量和元素值都没有发生变化。
但是需要注意的是,如果将张量的形状改变为不能容纳原先的元素数量,会抛出异常。比如现在有一个 2x3 的张量,如果将它改变为 1x4 的形状就会抛出异常。
另外,如果你使用 -1 作为一维大小,pytorch会自动计算这一维的大小,保证元素个数不变
还有一个函数 reshape() 也能达到相同的效果。
tensor = tensor.reshape(3, 2)
总之, .view() 和 reshape() 都能达到改变张量形状的目的,只需要注意不能改变元素的个数。
当我们学会如何创建张量之后,我们就可以来学习如何使用这些张量来进行一些数学运算。
在数学表示法中,我们将通过符号f:R→R来表示一元标量运算符(只接收一个输入)。这意味着该函数从任何实数(R)映射到另一个实数。同样,我们通过符号f:R,R→Rf:R,R→Rf:R,R→R表示二元标量运算符,这意味着该函数接收两个输入,并产生一个输出。给定同一形状的任意两个向量u和v和二元运算符f,我们可以得到向量c=F(u,v)c = F(u,v)c=F(u,v)。具体计算方法是ci←f(ui,vi)c_i \leftarrow f(u_i,v_i)ci←f(ui,vi),其中cic_ici、viv_ivi和viv_ivi分别是向量c、u和v中的元素。在这里,我们通过将标量函数升级为按元素向量运算来生成向量值F∶Rd,Rd一RdF∶R^d,R^d一R^dF∶Rd,Rd一Rd。
PyTorch 中支持多种张量间的运算符,这些运算符可以在不创建新的张量的情况下对原始张量进行修改。
常用的运算符包括:
例如:
import torch# 创建两个张量
tensor1 = torch.ones(2, 3)
tensor2 = torch.randn(2, 3)# 两个张量相加
tensor3 = tensor1 + tensor2
print(f"相加结果:{tensor3}")
# 两个张量相乘
tensor4 = tensor1 * tensor2
print(f"相乘结果:{tensor4}")
# 张量除以标量
tensor5 = tensor1 / 2
print(f"相除结果:{tensor5}")
相加结果:tensor([[0.1391, 1.9700, 0.8572],[3.3594, 1.6085, 1.4660]])
相乘结果:tensor([[-0.8609, 0.9700, -0.1428],[ 2.3594, 0.6085, 0.4660]])
相除结果:tensor([[0.5000, 0.5000, 0.5000],[0.5000, 0.5000, 0.5000]])
另外,还有一些其他的运算符, 如+=,-=,*=,/=,%=,**=
tensor1 += tensor2
tensor1 *= 2
这些运算符都是在原始张量上进行修改,而不会创建新的张量。
这些运算符都是基于element-wise运算的,也就是说对于两个张量,运算符会将它们的对应元素进行运算。这意味着它们的形状必须相同。
PyTorch也提供了一些其他的运算符,如:
这些函数可以更灵活地控制运算符的行为。
import torch# 创建两个张量
tensor1 = torch.ones(2, 3)
tensor2 = torch.randn(2, 3)# 使用torch.add()函数两个张量相加
tensor3 = torch.add(tensor1, tensor2)# 使用torch.mul()函数两个张量相乘
tensor4 = torch.mul(tensor1, tensor2)# 使用torch.div()函数张量除以标量
tensor5 = torch.div(tensor1, 2)
这些函数和运算符都是在张量间进行运算,而且都是基于 element-wise 运算的。这些运算符和函数都能很好的支持 GPU 加速,使得 PyTorch 成为了一种高效的深度学习框架。
在 PyTorch 中,可以使用 torch.cat() 函数将多个张量连接在一起,形成一个新的张量。连接操作可以在第 0 维(即行)或第 1 维(即列)上进行。
例如:
import torch# 创建三个 2x3 的张量
tensor1 = torch.randn(2, 3)
tensor2 = torch.randn(2, 3)
tensor3 = torch.randn(2, 3)# 在第 0 维上连接
result = torch.cat((tensor1, tensor2, tensor3), dim=0)
print(result)
tensor([[-0.1000, -1.5875, 1.5468],[-0.6155, -0.4775, -0.7122],[ 0.1312, 1.0378, -1.1289],[-0.6397, -1.2239, 0.0601],[-0.2370, 0.4329, 1.9026],[-1.4683, 2.1071, -1.7164]])
这里我们将三个 2x3 的张量在第 0 维(即行)上连接起来,得到了一个 6x3 的张量。
在 PyTorch 中,张量的广播机制允许在进行运算时使用不同形状的张量。它能自动地复制张量的元素,使得它们的形状相同。
例如:
import torch# 创建一个 2x3 的张量
tensor1 = torch.randn(2, 3)# 创建一个大小为 3 的张量
tensor2 = torch.randn(3)# 使用张量的广播机制进行运算
result = tensor1 + tensor2
print(result)
tensor([[ 0.0124, 0.9451, -0.3922],[-0.9794, 0.1206, -1.1299]])
在这个例子中,tensor1 是一个 2x3 的张量,而 tensor2 是一个大小为 3 的张量。在进行加法运算时,PyTorch 会自动地复制 tensor2 的元素,使得它们的形状与 tensor1 相同。
广播机制还可以应用在不同维度上,例如:
import torch# 创建一个 2x3 的张量
tensor1 = torch.randn(2, 3)# 创建一个 2x1 的张量
tensor2 = torch.randn(2, 1)# 使用张量的广播机制进行运算
result = tensor1 + tensor2
print(result)
tensor([[ 0.5422, -0.8242, 0.1485],[ 1.9900, -0.1229, 3.3772]])
Pytorch 在进行运算时会自动进行广播,这使得我们可以在不创建新的张量的情况下执行各种各样的数学运算,提高了编程的灵活性和效率。
与任何Python数组一样,张量中的元素都可以通过索引来访问,而且也是第一个元素的索引是0,最后一个元素的索引是-1,也可以指定范围以内包含第一个元素和最后一个之前元素。
索引是指使用下标来访问张量中的元素,例如:
import torch# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)# 访问第一行第二列的元素
print(tensor[0][1])# 也可以这样
print(tensor[0, 1])
tensor(-0.0790)
tensor(-0.0790)
切片是指使用切片语法来访问张量中的一个子集。例如:
import torch# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)# 访问第二行
print(tensor[1])# 访问第二列
print(tensor[:, 1])# 访问第二行第二列到最后一列
print(tensor[1, 1:])
tensor([ 0.3118, -0.8547, 0.5481])
tensor([-0.5568, -0.8547])
tensor([-0.8547, 0.5481])
索引和切片都可以用来访问张量中的元素,并且都可以赋值。例如:
import torch# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)# 使用索引赋值
tensor[0][1] = 0# 使用切片赋值
tensor[1] = torch.ones(3)
在 PyTorch 中,索引和切片可以结合使用,进行更细粒度的控制。例如:
import torch# 创建一个 2x3x4 的张量
tensor = torch.randn(2, 3, 4)# 访问第一个维度的第二个切片
print(tensor[1])# 访问第二个维度的第二个切片
print(tensor[:, 1])# 访问第三个维度的第二个切片
print(tensor[:, :, 1])
tensor([[ 1.4468, 0.4494, -0.8026, 0.6946],[ 1.1855, 0.2480, 0.1043, 0.1165],[-0.9049, 1.1424, -0.2831, -0.5333]])
tensor([[ 0.5936, 0.0597, -0.1426, 1.0866],[ 1.1855, 0.2480, 0.1043, 0.1165]])
tensor([[ 0.5400, 0.0597, -0.3470],[ 0.4494, 0.2480, 1.1424]])
这样就可以访问到不同维度上的元素,更灵活地进行操作。
另外,Pytorch还提供了一些函数来简化索引和切片,比如
torch.index_select(),torch.masked_select(),torch.narrow()等, 可以根据需要选择使用。
这些索引和切片的操作让我们可以轻松地访问张量中的元素,并对它们进行操作,提高了编程的灵活性和效率。
在 PyTorch 中,有一些操作可以节省内存。
例如:
例如:
import torch# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)# 使用 torch.view() 函数改变形状
tensor = tensor.view(3, 2)# 使用 torch.squeeze() 函数删除维度
tensor = tensor.squeeze()# 使用 torch.transpose() 函数进行转置
tensor = tensor.transpose(0, 1)
这些操作都是在不复制元素的情况下改变张量的形状,从而节省内存,提高程序的效率。
还有一种常用的操作是torch.clone()函数, 它会为张量中的元素创建一个副本.
例如:
import torch# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)# 使用 torch.clone() 函数创建副本
tensor2 = tensor.clone()
使用这些操作可以根据需要节省内存,提高程序的效率。
在 PyTorch 中,可以使用以下函数将张量转换为其他 Python 对象:
例如:
import torch
import numpy as np# 创建一个 2x3 的张量
tensor = torch.randn(2, 3)
print(f'张量:{tensor}')# 将张量转换为 Python 列表
python_list = tensor.tolist()
print(f'将张量转换为Python列表:{python_list}')# 将张量转换为 numpy 数组
numpy_array = tensor.numpy()
print(f'将张量转换为numpy数组:{numpy_array}')# 将 numpy 数组转换为张量
tensor2 = torch.tensor(numpy_array)
print(f'将numpy数组转换为张量:{tensor2}')
张量:tensor([[-1.1032, 1.7890, 0.6399],[ 1.2101, 0.0476, 0.7854]])
将张量转换为Python列表:[[-1.103205680847168, 1.788976788520813, 0.6398880481719971], [1.2101296186447144, 0.047570642083883286, 0.7854281067848206]]
将张量转换为numpy数组:[[-1.1032057 1.7889768 0.63988805][ 1.2101296 0.04757064 0.7854281 ]]
将numpy数组转换为张量:tensor([[-1.1032, 1.7890, 0.6399],[ 1.2101, 0.0476, 0.7854]])
这些函数可以方便地将张量转换为其他 Python 对象,这样可以在 PyTorch 中使用其他 Python 库,提高编程的灵活性和效率。
需要注意的是, 在转换后的对象中的操作并不会影响到原始的张量,如果需要可以再次转回去。
下一篇:笔试强训48天——day29