01-PyTorch基础知识:安装PyTorch环境和张量Tensor简介

2023-11-24 16:46:14 浏览数 (2)

本文为PyTorch Fundamentals[1]的学习笔记,对原文进行了翻译和编辑,本系列课程介绍和目录在《使用PyTorch进行深度学习系列》课程介绍[2]。 文章将最先在我的博客[3]发布,其他平台因为限制不能实时修改。 在微信公众号内无法嵌入超链接,可以点击底部阅读原文[4]获得更好的阅读体验。

本章将介绍将介绍如何安装和配置可以在GPU运行的PyTorch环境,介绍PyTorch的基本构建模块——张量(tensor)的概念及几种必要的张量运算方法。

目录:

  • 1.什么是 PyTorch?
  • 2.PyTorch环境配置
  • 3.为什么使用 PyTorch?
  • 4.导入 PyToch
  • 5.张量简介
    • 5.1 张量的基本类型
  • 6.创建张量的方法
    • 6.1 随机张量
    • 6.2 全0或全1张量
    • 6.3 创建范围张量
    • 6.4 创建相似张量
  • 7.张量的数据类型
  • 8.张量的操作(张量运算)
    • 8.1 基本操作
    • 8.2 矩阵乘法
    • 8.3 索引(index)和切片(slice)
    • 8.4 矩阵的转置
    • 8.5 为什么会用到矩阵乘法?
    • 8.6 求最小值、最大值、平均值、总和等(聚合)
    • 8.7 张量索引
    • 8.8更改张量数据类型
    • 8.9 更改张量的形状
  • 9.张量和 NumPy数组
  • 10.在 GPU 上运行张量
    • 10.1 检查是否有 GPU
    • 10.2 检查Pytorch是否可以使用GPU
    • 10.3 使用GPU运算
    • 10.4 将张量移回 CPU
  • 拓展阅读
  • 感谢

1.什么是 PyTorch?

PyTorch[5] 是一个开源机器学习和深度学习框架。PyTorch 允许您使用 Python 代码操作和处理数据并编写深度学习算法。

它是一个基于 Python 的科学计算包,使用 Tensor 作为其核心数据结构,类似于 Numpy 数组,不同的是,PyTorch 可以将用GPU来处理数据,提供许多深度学习的算法。

2.PyTorch环境配置

我们先来创建一个虚拟python环境:

代码语言:javascript复制
conda create -n dl
conda activate dl

我的电脑是Windows平台下的nvida GPU,接下来配置pytorch,分为三步:

第一步更新NVIDA显卡驱动到最近发布的稳定的版本:

官方驱动下载地址:https://www.nvidia.cn/Download/index.aspx?lang=cn

第二步安装CUDA Toolkit

CUDA Toolkit 安装前用以下命令查询机器上显卡最高支持的CUDA 版本:

终端输入:

代码语言:javascript复制
nvidia-smi

我的CUDA Version是12.2。

如果你没有安装cuda toolkit或者需要升级,可以去官网下载: https://developer.nvidia.com/cuda-toolkit-archive

第三步安装pytorch:

打开pytorch安装指导网站[6],选择合适的系统平台,关键是在compute platform选择一个不高于你电脑上的CUDA Version,复制命令安装。

代码语言:javascript复制
mamba install python pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia

如果你的conda解决环境很慢,可以试一试pip安装。

安装完成之后,运行如下命令检查:

代码语言:javascript复制
import torch
# 打印出正在使用的PyTorch和CUDA版本。
print(torch.__version__)
print(torch.version.cuda)

# 测试GPU是否生效
print(torch.cuda.is_available())  

3.为什么使用 PyTorch?

机器学习研究人员喜欢使用 PyTorch。截至 2022 年 2 月,PyTorch 是 Papers With Code 上最常用的深度学习框架[7],该网站用于跟踪机器学习研究论文及其附带的代码存储库。

PyTorch 易于学习和使用,足够灵活,可以在各种应用中使用,高效,以便我们可以处理巨大的现实数据集,并且足够准确,即使在输入数据存在不确定性的情况下也能提供正确的结果。

许多深度学习的应用使用了PyTorch,比如:

  • 文字生成图片的Stable Diffusion[8]

txt2img-stable2

  • 用于对象检测和语义分割的YOLOv5[9]系列(现在已经更新到YOLOv8[10]):

YOLOv8

  • 实时语音克隆Real-Time Voice Cloning[11]

image-20230920191736712

还有很多,不一一举例。

除上述通用领域的应用外,在一些专业领域的应用也在快速发展,比如医学领域,用PyTorch开发的开箱即用的解决方案nnU-Net[12]

nnU-Net overview

在GIS领域,ESRI官方提供了许多解决方案和预训练模型,有提取建筑物轮廓的模型:

使用ArcGIS Pro的深度学习模型提取建筑物轮廓

ArcGIS官方提供的预训练模型还有汽车检测 - 美国[13]云掩膜生成 (Sentinel-2)[14]人体检测(无人机影像)[15]土地覆盖分类 (Sentinel-2)[16]土地覆盖分类 (Landsat 8)[17]道路提取-全球[18]太阳能板检测 - 美国[19]树木检测[20]水体提取 (SAR) - 美国[21]等等。

4.导入 PyToch

注意:安装步骤参考 PyTorch 设置步骤[22]

让我们首先导入 PyTorch 并检查正在使用的版本。

代码语言:javascript复制
import torch
torch.__version__
>>> '2.0.1'

5.张量简介

张量,英文为Tensor,是机器学习的基本构建模块。

他们的工作是以数字方式表示数据。

例如,您可以将图像表示为形状为 [3, 224, 224] 的张量,这意味着 [colour_channels, height, width] ,因为图像具有 3 颜色通道(红色、绿色、蓝色),高度为 224 像素,宽度为 224 像素。

在张量语言(用于描述张量的语言)中,张量将具有三个维度,一个维度表示 colour_channelsheightwidth

5.1 张量的基本类型

PyTorch 有一个完整的文档页面专门用于介绍 `torch.Tensor`[23]类,可以花10 分钟阅读 `torch.Tensor` 上的文档[24]

5.1.1标量(scalar)

标量是单个数字,在pytorch中,它是0维张量。

代码语言:javascript复制
# Scalar
scalar = torch.tensor(7)
scalar
>>>  tensor(7

我们可以使用 ndim 属性检查张量的维度。

代码语言:javascript复制
scalar.ndim
>>> 0

如果我们想从张量中检索数字怎么办?

例如,将其从 torch.Tensor 转换为 Python 整数?

为此,我们可以使用 item() 方法。

代码语言:javascript复制
# 只适用于标量,不常用
scalar.item()
>>> 7
5.1.2向量(vector)

向量是一维张量,向量可以被视为标量值组成的列表。

例如,您可以使用向量 [3, 2] 来描述您房子中的 [bedrooms, bathrooms] 。或者您可以用 [3, 2, 2] 来描述您家里的 [bedrooms, bathrooms, car_parks]

这里的重要趋势是向量可以灵活地表示(与张量相同)。

代码语言:javascript复制
# 向量
vector = torch.tensor([7, 7])
vector
>>> tensor([7, 7])

你认为它有多少个维度?

代码语言:javascript复制
# Check the number of dimensions of vector
vector.ndim
>>> 1

这很奇怪, vector 包含两个数字,但只有一个维度。

有一个判断维度的小技巧:

您可以通过外部方括号 ( [ ) 的数量来判断 PyTorch 中张量的维数,并且只需要计算一侧。

vector 有1个方括号。

张量的另一个重要概念是它们的 shape 属性。形状告诉您其中的元素是如何排列的。

让我们看看 vector 的形状。

代码语言:javascript复制
# 检查vector的形状
vector.shape
>>> torch.Size([2])

上面返回 torch.Size([2]) 这意味着我们的向量的形状为 [2]

5.1.3矩阵(matrix)

现在让我们看一个矩阵(matrix)

代码语言:javascript复制
# Matrix
MATRIX = torch.tensor([[7, 8], 
                       [9, 10]])
MATRIX
>>> tensor([[ 7,  8],
        [ 9, 10]])

检查矩阵的纬度:

代码语言:javascript复制
MATRIX.ndim
>>> 2

MATRIX 有两个维度。

矩阵的形状:

代码语言:javascript复制
MATRIX.shape
>>> torch.Size([2, 2])

MATRIX 的深度为两个元素,宽度为两个元素。

6.创建张量的方法

代码语言:javascript复制
# Tensor
TENSOR = torch.tensor([[[1, 2, 3],
                        [3, 6, 9],
                        [2, 4, 5]]])
TENSOR
>>>
tensor([[[1, 2, 3],
         [3, 6, 9],
         [2, 4, 5]]])

张量几乎可以代表任何东西。

我们刚刚创建的可能是一家牛排和杏仁黄油商店的销售数字。

a simple tensor in google sheets showing day of week, steak sales and almond butter sales

查看TENSOR的维度:

代码语言:javascript复制
TENSOR.ndim
>>> 3

查看TENSOR的形状:

代码语言:javascript复制
# Check shape of TENSOR
TENSOR.shape
>>> torch.Size([1, 3, 3])

这意味着存在 1 个 3 x 3 的维度。

注意:您可能已经注意到我使用小写字母表示 scalarvector ,使用大写字母表示 MATRIXTENSOR 。在实践中,您经常会看到用小写字母表示的标量和向量,例如 ya 。矩阵和张量表示为大写字母,例如 XW


我们来总结一下。


6.1 随机张量

机器学习模型通常从大型随机数张量开始,并在处理数据时调整这些随机数以更好地表示数据。

As a data scientist, you can define how the machine learning model starts (initialization), looks at data (representation) and updates (optimization) its random numbers. 作为数据科学家,您可以定义机器学习模型如何启动(初始化)、查看数据(表示)和更新(优化)其随机数。

We'll get hands on with these steps later on. 稍后我们将实际操作这些步骤。

让我们看看如何创建随机数张量。

我们可以使用 torch.rand() 并传入 size 参数来实现。

创建一个大小为3x4的随机张量:

代码语言:javascript复制
random_tensor = torch.rand(size=(3, 4))
random_tensor, random_tensor.dtype
>>> 
(tensor([[0.6541, 0.4807, 0.2162, 0.6168],
         [0.4428, 0.6608, 0.6194, 0.8620],
         [0.2795, 0.6055, 0.4958, 0.5483]]),
 torch.float32)

torch.rand() 的灵活性在于我们可以将 size 调整为我们想要的任何内容。

例如,假设您想要一个常见图像形状 [224, 224, 3] ( [height, width, color_channels ]) 的随机张量:

代码语言:javascript复制
random_image_size_tensor = torch.rand(size=(224, 224, 3))
random_image_size_tensor.shape, random_image_size_tensor.ndim
>>> 
(torch.Size([224, 224, 3]), 3)

6.2 全0或全1张量

创建大小为3x4,数值都为0的张量:

代码语言:javascript复制
# Create a tensor of all zeros
zeros = torch.zeros(size=(3, 4))
zeros, zeros.dtype
>>> 
(tensor([[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]),
 torch.float32)

创建大小为3x4,数值都为1则用 torch.ones() 代替torch.zeros()

6.3 创建范围张量

使用 torch.arange(start, end, step) 来执行此操作。

注意:在 Python 中,您可以使用 range() 创建范围。然而在 PyTorch 中, torch.range() 已被弃用,并且将来可能会显示错误。

代码语言:javascript复制
# Create a range of values 0 to 10
zero_to_ten = torch.arange(start=0, end=10, step=1)
zero_to_ten
>>>
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

6.4 创建相似张量

有时您可能需要某种类型的一个张量与另一个张量具有相同的形状。

例如,与前一个张量具有相同形状的全零张量。为此可以使用 torch.zeros_like(input)torch.ones_like(input) ,它们分别返回一个用零或 1 填充的张量,其形状与 input 相同。

In [19]: 在[19]中:

代码语言:javascript复制
# Can also create a tensor of zeros similar to another tensor
ten_zeros = torch.zeros_like(input=zero_to_ten) # will have same shape
ten_zeros
>>> 
tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])


7.张量的数据类型

PyTorch 中有许多不同的张量数据类型[25]。 最常见的类型(通常是默认类型)是 torch.float32torch.float 。 这称为“32 位浮点”。还有 16 位浮点( torch.float16torch.half )和 64 位浮点( torch.float64torch.double )。 所有这些的原因都与计算精度有关。精度是用于描述数字的细节量。 精度值越高(8、16、32),就越详细,因此用于表达数字的数据就越多。这在深度学习和数值计算中很重要,因为您要进行大量操作,需要计算的细节越多,需要使用的计算量就越多。因此,精度较低的数据类型通常计算速度更快,但会牺牲准确性等评估指标的一些性能(计算速度更快,但准确性较低)。

  • 有关所有可用张量数据类型的列表,请参阅 PyTorch 文档[26]
  • 阅读维基百科页面:[了解计算精度的概述](https://en.wikipedia.org/wiki/Precision_(computer_science "了解计算精度的概述"))。

创建一些具有特定数据类型的张量。我们可以使用 dtype 参数来做到这一点。

In [20]: 在[20]中:

代码语言:javascript复制
float_32_tensor = torch.tensor([3.0, 6.0, 9.0],
                               dtype=None, # defaults to None:torch.float32
                               device=None, 
                               requires_grad=False) # 如果为True,则此tensor用于深度学习的时候可以被改变

float_32_tensor.shape, float_32_tensor.dtype, float_32_tensor.device
>>>
(torch.Size([3]), torch.float32, device(type='cpu'))

除了形状问题(张量形状不匹配)之外,您在 PyTorch 中遇到的其他两个最常见问题是数据类型和设备问题。

当您在 PyTorch 中遇到问题时,通常与上述三个属性之一有关。我们用用如下代码去检查:

代码语言:javascript复制
print(some_tensor)
print(f"Shape of tensor: {some_tensor.shape}")
print(f"Datatype of tensor: {some_tensor.dtype}")
print(f"Device tensor is stored on: {some_tensor.device}") 

8.张量的操作(张量运算)

8.1 基本操作

让我们从一些基本运算开始,加法 ( )、减法 ( - )、乘法 ( * )。

代码语言:javascript复制
x = torch.tensor([1.0, 2, 4, 8]) 
y = torch.tensor([2, 2, 2, 2]) 
x   y, x - y, x * y, x / y, x ** y # 运算符是求幂运算
代码语言:javascript复制
(tensor([ 3., 4., 6., 10.]), tensor([-1., 0., 2., 6.]), tensor([ 2., 4., 8., 16.]), tensor([0.5000, 1.0000, 2.0000, 4.0000]), tensor([ 1., 4., 16., 64.]))

8.2 矩阵乘法

机器学习和深度学习算法(如神经网络)中最常见的运算之一是矩阵乘法。

像这样的矩阵乘法也被称为两个矩阵的点积。

在http://matrixmultiplication.xyz/网站上提供了可视化矩阵的动画:

矩阵乘法动画

PyTorch 在 torch.matmul() 方法中实现矩阵乘法功能。

让我们创建一个张量并对其执行逐元素乘法和矩阵乘法。

代码语言:javascript复制
import torch
tensor = torch.tensor([1, 2, 3])
tensor.shape
>>>
torch.Size([3])

对于我们的 tensor 变量,其值为 [1, 2, 3]

In [32]: 在[32]中:

代码语言:javascript复制
# 元素乘法
tensor * tensor
>>>
tensor([1, 4, 9])

代码语言:javascript复制
# 矩阵乘法
torch.matmul(tensor, tensor)
# 也用"@" 表示矩阵相乘,但是不推荐,内置的 `torch.matmul()` 方法速度更快。
# 还可以使用 `torch.mm()` 替代 `torch.matmul()` 
tensor @ tensor
>>> 
tensor(14)

通过对比元素乘法和矩阵乘法,我们知道了矩阵陈发就是按元素乘法之后再进行求和。

8.3 索引(index)和切片(slice)

就像在任何其他Python数组中一样, 张量中的元素可以通过索引访问。 与任何Python数组一样:第一个元素的索引是0,最后一个元素索引是-1;可以指定范围以包含第一个元素和最后一个之前的元素。 如下所示,我们可以用[-1]选择最后一个元素,可以用[1:3]选择第二个和第三个元素:

代码语言:javascript复制
X[-1], X[1:3]

image-20230926182901602

如果我们想为多个元素赋值相同的值,我们只需要索引所有元素,然后为它们赋值。例如,[0:2, :]访问第1行和第2行,其中“:”代表沿轴1(列)的所有元素。虽然我们讨论的是矩阵的索引,但这也适用于向量和超过2个维度的张量。

代码语言:javascript复制
X[0:2, :] = 12
X

8.4 矩阵的转置

image-20230926182814216

代码语言:javascript复制
B = A.T

8.5 为什么会用到矩阵乘法?

神经网络充满了矩阵乘法和点积。深度学习中使用矩阵乘法的主要原因是矩阵乘法的线性变换性质并行计算的效率

在深度学习中,神经网络的基本组成部分是神经元(或称为节点)和它们之间的连接权重。神经网络的前向传播过程涉及大量的线性变换和非线性激活函数的组合。而矩阵乘法提供了一种高效的方式来表示和计算这些线性变换。

[torch.nn.Linear()](https://pytorch.org/docs/1.9.1/generated/torch.nn.Linear.html "torch.nn.Linear( "torch.nn.Linear()")") 模块(我们稍后会看到它的实际应用),也称为前馈层或全连接层,实现输入 x 和输入之间的矩阵乘法权重矩阵 A

y = xcdot{A^T} b

说明:

  • x 是该层的输入(深度学习是诸如 torch.nn.Linear() 之类的层以及其他层的堆叠)。
  • A 是该层创建的权重矩阵,它最初是随机数,随着神经网络学习更好地表示数据中的模式而进行调整(注意“ T ”,这是因为权重矩阵被转置了)。 注意:您可能还经常看到 W 或其他字母(如 X )用于展示权重矩阵。
  • b 是bias,表示权重或者偏差。
  • y 是输出(对输入进行操作,希望发现其中的模式)。

这是一个线性函数(您可能在高中或其他地方见过类似

y = mx b

的函数),可以用来画直线!

在神经网络中的线性层通常这样表示:

代码语言:javascript复制
torch.manual_seed(42) # 用来保证随机值是和我一样,用来比对结果。
# 使用矩阵乘法
linear = torch.nn.Linear(in_features=2, # in_features :匹配输入形状的维度 
                         out_features=6) # out_features :描述输出值 

x = tensor_A
output = linear(x)

print(f"Input shape: {x.shape}n")
print(f"Output:n{output}nnOutput shape: {output.shape}")
>>> 
Input shape: torch.Size([3, 2])

Output:
tensor([[2.2368, 1.2292, 0.4714, 0.3864, 0.1309, 0.9838],
        [4.4919, 2.1970, 0.4469, 0.5285, 0.3401, 2.4777],
        [6.7469, 3.1648, 0.4224, 0.6705, 0.5493, 3.9716]],
       grad_fn=<AddmmBackward0>)

Output shape: torch.Size([3, 6])

matrix_multiplication_is_all_you_need

8.6 求最小值、最大值、平均值、总和等(聚合)

首先我们创建一个张量,然后求它的最大值、最小值、平均值和总和。

代码语言:javascript复制
# 创建一个张量
x = torch.arange(0, 100, 10)
x
>>>
tensor([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])

现在让我们执行一些聚合操作。

代码语言:javascript复制
print(f"最小值 Minimum: {x.min()}")
print(f"最大值Maximum: {x.max()}")
# print(f"平均值 Mean: {x.mean()}") # this will error
print(f"平均值 Mean: {x.type(torch.float32).mean()}") # 用于浮点型数据类型
print(f"总和 Sum: {x.sum()}")
>>>
Minimum: 0
Maximum: 90
Mean: 45.0
Sum: 450

您还可以使用 torch 方法执行与上面相同的操作。

代码语言:javascript复制
torch.max(x), torch.min(x), torch.mean(x.type(torch.float32)), torch.sum(x)
>>>
(tensor(90), tensor(0), tensor(45.), tensor(450))

8.7 张量索引

您还可以分别使用 [torch.argmax()](https://pytorch.org/docs/stable/generated/torch.argmax.html "torch.argmax( "torch.argmax()")") 和 [torch.argmin()](https://pytorch.org/docs/stable/generated/torch.argmin.html "torch.argmin( "torch.argmin()")") 查找最大值或最小值出现的张量索引。

代码语言:javascript复制
tensor = torch.arange(10, 100, 10)
print(f"Tensor: {tensor}")


print(f"最大值所在的索引值: {tensor.argmax()}")
print(f"最小值所在的索引值: {tensor.argmin()}")
>>>
Tensor: tensor([10, 20, 30, 40, 50, 60, 70, 80, 90])
Index where max value occurs: 8
Index where min value occurs: 0

8.8更改张量数据类型

深度学习操作的三个常见问题之一就是:张量具有不同的数据类型。如果一个张量位于 torch.float64 中,另一个张量位于 torch.float32 中,则可能会遇到一些错误。您可以使用 torch.Tensor.type(dtype=None) 更改张量的数据类型,其中 dtype 参数是您要使用的数据类型。

首先,我们将创建一个张量并检查它的数据类型(默认为 torch.float32 )。

代码语言:javascript复制
# Create a tensor and check its datatype
tensor = torch.arange(10., 100., 10.)
tensor.dtype
>>> torch.float32

现在我们将创建另一个与之前相同的张量,但将其数据类型更改为 torch.float16

代码语言:javascript复制
# Create a float16 tensor
tensor_float16 = tensor.type(torch.float16)
tensor_float16
>>>  tensor([10., 20., 30., 40., 50., 60., 70., 80., 90.], dtype=torch.float16)

8.9 更改张量的形状

有重塑、堆叠、挤压和解压:

方法

单行描述

torch.reshape(input, shape)

重塑 input 到 shape (如果兼容),也可以使用 torch.Tensor.reshape()。

Tensor.view(shape)

返回不同 shape 中的原始张量视图,但与原始张量共享相同的数据。

torch.stack(tensors, dim=0)

沿着新的维度(dim)连接 tensors 的序列,所有 tensors 必须具有相同的大小。

torch.squeeze(input)

挤压 input 以移除值为 1 的所有尺寸。

torch.unsqueeze(input, dim)

返回在 dim 处添加了维度值 1 的 input。

torch.permute(input, dims)

返回原始 input 的视图,其尺寸被置换(重新排列)为 dims。

深度学习模型(神经网络)都是以某种方式操纵张量。由于矩阵乘法的规则,如果形状不匹配,就会遇到错误。这些方法可帮助您确保张量的正确元素与其他张量的正确元素混合。

举例说明:

代码语言:javascript复制
import torch
x = torch.arange(1., 8.)
x, x.shape
>>>
(tensor([1., 2., 3., 4., 5., 6., 7.]), torch.Size([7]))
1)Reshape

现在让我们使用 torch.reshape() 增加一个维度。

代码语言:javascript复制
# 增加一个维度
x_reshaped = x.reshape(1, 7)
x_reshaped, x_reshaped.shape
>>>
(tensor([[1., 2., 3., 4., 5., 6., 7.]]), torch.Size([1, 7]))
2)View

我们还可以使用 torch.view() 更改视图。

代码语言:javascript复制
# Change view (keeps same data as original but changes view)
# See more: https://stackoverflow.com/a/54507446/7900723
z = x.view(1, 7)
z, z.shape
>>>
(tensor([[1., 2., 3., 4., 5., 6., 7.]]), torch.Size([1, 7]))

注意,使用 torch.view() 更改张量的视图实际上只会创建同一张量的新视图,因此改变视图也会改变原始张量。

代码语言:javascript复制
# Changing z changes x
z[:, 0] = 5
z, x
>>>
(tensor([[5., 2., 3., 4., 5., 6., 7.]]), tensor([5., 2., 3., 4., 5., 6., 7.]))
3)Stack

如果我们想将新张量堆叠五次,我们可以使用 torch.stack() 来实现。

代码语言:javascript复制
# Stack tensors on top of each other
x_stacked = torch.stack([x, x, x, x], dim=0) # 同pandas的axis,按行堆叠
>>>
tensor([[5., 2., 3., 4., 5., 6., 7.],
        [5., 2., 3., 4., 5., 6., 7.],
        [5., 2., 3., 4., 5., 6., 7.],
        [5., 2., 3., 4., 5., 6., 7.]])
4)Squeeze

为此,您可以使用 torch.squeeze() (将张量压缩为仅具有超过 1 的维度)。

代码语言:javascript复制
print(f"Previous tensor: {x_reshaped}")
print(f"Previous shape: {x_reshaped.shape}")

# Remove extra dimension from x_reshaped
x_squeezed = x_reshaped.squeeze()
print(f"nNew tensor: {x_squeezed}")
print(f"New shape: {x_squeezed.shape}")

>>>
Previous tensor: tensor([[5., 2., 3., 4., 5., 6., 7.]])
Previous shape: torch.Size([1, 7])

New tensor: tensor([5., 2., 3., 4., 5., 6., 7.])
New shape: torch.Size([7])

5)Unsqueeze

要执行 torch.squeeze() 的相反操作,您可以使用 torch.unsqueeze() 在特定索引处添加维度值 1。

代码语言:javascript复制
print(f"Previous tensor: {x_squeezed}")
print(f"Previous shape: {x_squeezed.shape}")

## Add an extra dimension with unsqueeze
x_unsqueezed = x_squeezed.unsqueeze(dim=0)
print(f"nNew tensor: {x_unsqueezed}")
print(f"New shape: {x_unsqueezed.shape}")
>>>
Previous tensor: tensor([5., 2., 3., 4., 5., 6., 7.])
Previous shape: torch.Size([7])

New tensor: tensor([[5., 2., 3., 4., 5., 6., 7.]])
New shape: torch.Size([1, 7])

6)Permute 重新排列

您还可以使用 torch.permute(input, dims) 重新排列轴值的顺序,其中 input 将变成具有新 dims 的视图。

代码语言:javascript复制
x_original = torch.rand(size=(224, 224, 3)) # 可以理解为一张图片的高、宽和颜色通道

x_permuted = x_original.permute(2, 0, 1) # 重新排“列” 0->1, 1->2, 2->0

print(f"Previous shape: {x_original.shape}")
print(f"New shape: {x_permuted.shape}")
>>> 
Previous shape: torch.Size([224, 224, 3])
New shape: torch.Size([3, 224, 224])

9.张量和 NumPy数组

由于 NumPy 是一个流行的 Python 数值计算库,PyTorch 具有与其良好交互的功能。 NumPy 到 PyTorch(以及再次返回)的两种主要方法是:

  • [torch.from_numpy(ndarray)](https://pytorch.org/docs/stable/generated/torch.from_numpy.html "torch.from_numpy(ndarray "torch.from_numpy(ndarray)")") - NumPy 数组转为PyTorch 张量。
  • [torch.Tensor.numpy()](https://pytorch.org/docs/stable/generated/torch.Tensor.numpy.html "torch.Tensor.numpy( "torch.Tensor.numpy()")") - PyTorch 张量转为NumPy 数组。

踩坑:

1.默认情况下,NumPy 数组是使用数据类型 float64 创建的,如果将其转换为 PyTorch 张量,它将保留相同的数据类型(如上所述)。但是,许多 PyTorch 计算默认使用 float32 。因此,如果您想转换 NumPy 数组 (float64) -> PyTorch 张量 (float64) -> PyTorch 张量 (float32),您可以使用 tensor = torch.from_numpy(array).type(torch.float32)

2.因为我们在上面重新赋值了张量tensor,所以如果更改张量,数组array将保持不变。

10.在 GPU 上运行张量

深度学习算法需要大量的数值运算。

默认情况下,这些操作通常在 CPU(计算机处理单元)上完成。

10.1 检查是否有 GPU

要检查您是否有权访问 Nvidia GPU,您可以运行 !nvidia-smi ,其中 ! (也称为 bang)表示“在命令行上运行”。

如果您有 GPU,上面的行将输出如下内容:

image-20230926215008208

10.2 检查Pytorch是否可以使用GPU

You can test if PyTorch has access to a GPU using [torch.cuda.is_available()](https://pytorch.org/docs/stable/generated/torch.cuda.is_available.html#torch.cuda.is_available "torch.cuda.is_available( "torch.cuda.is_available()")"). 您可以使用 torch.cuda.is_available() 测试 PyTorch 是否可以访问 GPU。

代码语言:javascript复制
# Check for GPU
import torch
torch.cuda.is_available()

如果上面的输出 True ,PyTorch 可以使用 GPU,如果输出 False ,则不能使用 GPU,如果你没有安装成功请参考安装指南。

10.3 使用GPU运算

代码语言:javascript复制
# Set device type
device = "cuda" if torch.cuda.is_available() else "cpu"
device

如果上面的输出 "cuda" 意味着我们可以将所有 PyTorch 代码设置为使用可用的 CUDA 设备(GPU),如果输出 "cpu" ,我们的 PyTorch 代码将坚持使用中央处理器。

通过调用 to(device) 将张量(和模型,我们稍后会看到)放置在特定设备上。其中 device 是您希望张量(或模型)前往的目标设备。

让我们尝试创建一个张量并将其放在 GPU 上(如果可用):

代码语言:javascript复制
# Create tensor (default on CPU)
tensor = torch.tensor([1, 2, 3])

# Tensor not on GPU
print(tensor, tensor.device)

# Move tensor to GPU (if available)
tensor_on_gpu = tensor.to(device)
tensor_on_gpu
>>>
tensor([1, 2, 3], device='cuda:0')

device='cuda:0' ,这意味着它存储在第 0 个可用的 GPU 上(GPU 的索引为 0,如果有两个 GPU 可用,则它们将是 'cuda:0''cuda:1' )。

10.4 将张量移回 CPU

tensor_on_gpu 上使用 torch.Tensor.numpy() 方法将张量移到cpu:

代码语言:javascript复制
# If tensor is on GPU, can't transform it to NumPy (this will error)
tensor_on_gpu.numpy()


拓展阅读

  • `torch.Tensor`[27]`torch.cuda`[28] 的文档。
  • 花 1 小时浏览 PyTorch 基础教程[29](我推荐快速入门[30]张量[31]部分)。

感谢

感谢原作者 Daniel Bourke,访问https://www.learnpytorch.io/[32]可以阅读英文原文,点击原作者的Github仓库:https://github.com/mrdbourke/pytorch-deep-learning/[33]可以获得帮助和其他信息。

本文同样遵守遵守 MIT license[34],不受任何限制,包括但不限于权利

使用、复制、修改、合并、发布、分发、再许可和/或出售。但需标明原始作者的许可信息:renhai-lab:https://cdn.renhai-lab.tech/

如果你觉得本系列文章有用,欢迎关注博客,点赞和收藏,也欢迎在评论区讨论:

参考资料

[1]

PyTorch Fundamentals: https://www.learnpytorch.io/00_pytorch_fundamentals/#what-is-pytorch

[2]

《使用PyTorch进行深度学习系列》课程介绍: https://cdn.renhai-lab.tech/archives/DL-Home

[3]

我的博客: https://cdn.renhai-lab.tech/categories/deep-learning

[4]

阅读原文: https://cdn.renhai-lab.tech/archives/DL-01-pytorch

[5]

PyTorch: https://pytorch.org/

[6]

pytorch安装指导网站: https://pytorch.org/get-started/locally/

[7]

Papers With Code 上最常用的深度学习框架: https://paperswithcode.com/trends

[8]

Stable Diffusion: https://github.com/CompVis/stable-diffusion

[9]

YOLOv5: https://github.com/ultralytics/yolov5

[10]

YOLOv8: https://github.com/ultralytics/ultralytics

[11]

Real-Time Voice Cloning: https://github.com/CorentinJ/Real-Time-Voice-Cloning

[12]

nnU-Net: https://github.com/MIC-DKFZ/nnUNet

[13]

汽车检测 - 美国: https://doc.arcgis.com/zh-cn/pretrained-models/latest/imagery/introduction-to-car-detection-usa.htm

[14]

云掩膜生成 (Sentinel-2): https://doc.arcgis.com/zh-cn/pretrained-models/latest/imagery/introduction-to-car-detection-usa.htm

[15]

人体检测(无人机影像): https://doc.arcgis.com/zh-cn/pretrained-models/latest/imagery/introduction-to-human-detection-drone-imagery-.htm

[16]

土地覆盖分类 (Sentinel-2): https://doc.arcgis.com/zh-cn/pretrained-models/latest/imagery/introduction-to-land-cover-classification-sentinel-2-.htm

[17]

土地覆盖分类 (Landsat 8): https://doc.arcgis.com/zh-cn/pretrained-models/latest/imagery/introduction-to-common-object-detection.htm

[18]

道路提取-全球: https://doc.arcgis.com/zh-cn/pretrained-models/latest/imagery/introduction-to-common-object-detection.htm

[19]

太阳能板检测 - 美国: https://doc.arcgis.com/zh-cn/pretrained-models/latest/imagery/introduction-to-solar-panel-detection-usa.htm

[20]

树木检测: https://doc.arcgis.com/zh-cn/pretrained-models/latest/imagery/introduction-to-common-object-detection.htm

[21]

水体提取 (SAR) - 美国: https://doc.arcgis.com/zh-cn/pretrained-models/latest/imagery/introduction-to-common-object-detection.htm

[22]

PyTorch 设置步骤: https://pytorch.org/get-started/locally/

[23]

torch.Tensor: https://pytorch.org/docs/stable/tensors.html

[24]

torch.Tensor 上的文档: https://pytorch.org/docs/stable/tensors.html

[25]

数据类型: https://pytorch.org/docs/stable/tensors.html#data-types

[26]

PyTorch 文档: https://pytorch.org/docs/stable/tensors.html#data-types

[27]

torch.Tensor: https://pytorch.org/docs/stable/tensors.html#torch-tensor

[28]

torch.cuda: https://pytorch.org/docs/master/notes/cuda.html#cuda-semantics

[29]

PyTorch 基础教程: https://pytorch.org/tutorials/beginner/basics/intro.html

[30]

快速入门: https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html

[31]

张量: https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html

[32]

https://www.learnpytorch.io/: https://www.learnpytorch.io/

[33]

https://github.com/mrdbourke/pytorch-deep-learning/: https://github.com/mrdbourke/pytorch-deep-learning/

[34]

MIT license: https://github.com/renhai-lab/pytorch-deep-learning/blob/cb770bbe688f5950421a76c8b3a47aaa00809c8c/LICENSE

[35]

我的博客: https://cdn.renhai-lab.tech/

[36]

我的GITHUB: https://github.com/renhai-lab

[37]

我的GITEE: https://gitee.com/renhai-lab

[38]

我的知乎: https://www.zhihu.com/people/Ing_ideas

0 人点赞