PyTorch 简介
PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由C++实现,应用于人工智能领域,如计算机视觉和自然语言处理。
PyTorch 最初由 Meta Platforms 的人工智能研究团队开发,现在属 于Linux 基金会的一部分。
许多深度学习软件都是基于 PyTorch 构建的,包括特斯拉自动驾驶、Uber 的 Pyro、Hugging Face 的 Transformers、 PyTorch Lightning 和 Catalyst。
PyTorch 主要有两大特征:
- 类似于 NumPy 的张量计算,能在 GPU 或 MPS 等硬件加速器上加速。
- 基于带自动微分系统的深度神经网络。
PyTorch 包括 torch.autograd、torch.nn、torch.optim 等子模块。
PyTorch 包含多种损失函数,包括 MSE(均方误差 = L2 范数)、交叉熵损失和负熵似然损失(对分类器有用)等。
学习路线图和视频教程找下面小助手领取即可↓↓↓
PyTorch 特性
-
动态计算图(Dynamic Computation Graphs): PyTorch 的计算图是动态的,这意味着它们在运行时构建,并且可以随时改变。这为实验和调试提供了极大的灵活性,因为开发者可以逐行执行代码,查看中间结果。
-
自动微分(Automatic Differentiation): PyTorch 的自动微分系统允许开发者轻松地计算梯度,这对于训练深度学习模型至关重要。它通过反向传播算法自动计算出损失函数对模型参数的梯度。
-
张量计算(Tensor Computation): PyTorch 提供了类似于 NumPy 的张量操作,这些操作可以在 CPU 和 GPU 上执行,从而加速计算过程。张量是 PyTorch 中的基本数据结构,用于存储和操作数据。
-
丰富的 API: PyTorch 提供了大量的预定义层、损失函数和优化算法,这些都是构建深度学习模型的常用组件。
-
多语言支持: PyTorch 虽然以 Python 为主要接口,但也提供了 C++ 接口,允许更底层的集成和控制。
动态计算图(Dynamic Computation Graph)
PyTorch 最显著的特点之一是其动态计算图的机制。
与 TensorFlow 的静态计算图(graph)不同,PyTorch 在执行时构建计算图,这意味着在每次计算时,图都会根据输入数据的形状自动变化。
动态计算图的优点:
- 更加灵活,特别适用于需要条件判断或递归的场景。
- 方便调试和修改,能够直接查看中间结果。
- 更接近 Python 编程的风格,易于上手。
张量(Tensor)与自动求导(Autograd)
PyTorch 中的核心数据结构是 张量(Tensor),它是一个多维矩阵,可以在 CPU 或 GPU 上高效地进行计算。张量的操作支持自动求导(Autograd)机制,使得在反向传播过程中自动计算梯度,这对于深度学习中的梯度下降优化算法至关重要。
张量(Tensor):
- 支持在 CPU 和 GPU 之间进行切换。
- 提供了类似 NumPy 的接口,支持元素级运算。
- 支持自动求导,可以方便地进行梯度计算。
自动求导(Autograd):
- PyTorch 内置的自动求导引擎,能够自动追踪所有张量的操作,并在反向传播时计算梯度。
- 通过
requires_grad
属性,可以指定张量需要计算梯度。 - 支持高效的反向传播,适用于神经网络的训练。
模型定义与训练
PyTorch 提供了 torch.nn
模块,允许用户通过继承 nn.Module
类来定义神经网络模型。使用 forward
函数指定前向传播,自动反向传播(通过 autograd
)和梯度计算也由 PyTorch 内部处理。
神经网络模块(torch.nn):
- 提供了常用的层(如线性层、卷积层、池化层等)。
- 支持定义复杂的神经网络架构(包括多输入、多输出的网络)。
- 兼容与优化器(如
torch.optim
)一起使用。
GPU 加速
PyTorch 完全支持在 GPU 上运行,以加速深度学习模型的训练。通过简单的 .to(device)
方法,用户可以将模型和张量转移到 GPU 上进行计算。PyTorch 支持多 GPU 训练,能够利用 NVIDIA CUDA 技术显著提高计算效率。
GPU 支持:
- 自动选择 GPU 或 CPU。
- 支持通过 CUDA 加速运算。
- 支持多 GPU 并行计算(
DataParallel
或torch.distributed
)。
生态系统与社区支持
PyTorch 作为一个开源项目,拥有一个庞大的社区和生态系统。它不仅在学术界得到了广泛的应用,也在工业界,特别是在计算机视觉、自然语言处理等领域中得到了广泛部署。PyTorch 还提供了许多与深度学习相关的工具和库,如:
- torchvision:用于计算机视觉任务的数据集和模型。
- torchtext:用于自然语言处理任务的数据集和预处理工具。
- torchaudio:用于音频处理的工具包。
- PyTorch Lightning:一种简化 PyTorch 代码的高层库,专注于研究和实验的快速迭代。
与其他框架的对比
PyTorch 由于其灵活性、易用性和社区支持,已经成为很多深度学习研究者和开发者的首选框架。
TensorFlow vs PyTorch:
- PyTorch 的动态计算图使得它更加灵活,适合快速实验和研究;而 TensorFlow 的静态计算图在生产环境中更具优化空间。
- PyTorch 在调试时更加方便,TensorFlow 则在部署上更加成熟,支持更广泛的硬件和平台。
- 近年来,TensorFlow 也引入了动态图(如 TensorFlow 2.x),使得两者在功能上趋于接近。
- 其他深度学习框架,如 Keras、Caffe 等也有一定应用,但 PyTorch 由于其灵活性、易用性和社区支持,已经成为很多深度学习研究者和开发者的首选框架。
特性 | TensorFlow | PyTorch |
---|---|---|
开发公司 | Facebook (FAIR) | |
计算图类型 | 静态计算图(定义后再执行) | 动态计算图(定义即执行) |
灵活性 | 低(计算图在编译时构建,不易修改) | 高(计算图在执行时动态创建,易于修改和调试) |
调试 | 较难(需要使用 tf.debugging 或外部工具调试) | 容易(可以直接在 Python 中进行调试) |
易用性 | 低(较复杂,API 较多,学习曲线较陡峭) | 高(API 简洁,语法更加接近 Python,容易上手) |
部署 | 强(支持广泛的硬件,如 TensorFlow Lite、TensorFlow.js) | 较弱(部署工具和平台相对较少,虽然有 TensorFlow 支持) |
社区支持 | 很强(成熟且庞大的社区,广泛的教程和文档) | 很强(社区活跃,特别是在学术界,快速发展的生态) |
模型训练 | 支持分布式训练,支持多种设备(如 CPU、GPU、TPU) | 支持分布式训练,支持多 GPU、CPU 和 TPU |
API 层级 | 高级API:Keras;低级API:TensorFlow Core | 高级API:TorchVision、TorchText 等;低级API:Torch |
性能 | 高(优化方面成熟,适合生产环境) | 高(适合研究和原型开发,生产性能也在提升) |
自动求导 | 通过 tf.GradientTape 实现动态求导(较复杂) | 通过 autograd 动态求导(更简洁和直观) |
调优与可扩展性 | 强(支持在多平台上运行,如 TensorFlow Serving 等) | 较弱(虽然在学术和实验环境中表现优越,但生产环境支持相对较少) |
框架灵活性 | 较低(TensorFlow 2.x 引入了动态图特性,但仍不完全灵活) | 高(动态图带来更高的灵活性) |
支持多种语言 | 支持多种语言(Python, C++, Java, JavaScript, etc.) | 主要支持 Python(但也有 C++ API) |
兼容性与迁移 | TensorFlow 2.x 与旧版本兼容性较好 | 与 TensorFlow 兼容性差,迁移较难 |
PyTorch 是一个强大且灵活的深度学习框架,适合学术研究和工业应用。它的动态计算图、自动求导机制、GPU 加速等特点,使得其成为深度学习研究和实验中不可或缺的工具。
PyTorch 安装
PyTorch 是一个流行的深度学习框架,支持 CPU 和 GPU 计算。
检查 Python 和 pip 版本
首先,确保你已安装 Python 和 pip,并且它们的版本满足 PyTorch 的要求。
在终端或命令行中检查版本:
python --version pip --version
安装 PyTorch
PyTorch 官方提供了几种安装方法,可以通过 pip 或 conda 进行安装。
使用 pip 安装
使用 pip 安装 pytorch:
pip3 install torch torchvision
使用 conda 安装
如果你使用 Anaconda 或 Miniconda 管理 Python 环境,使用 conda 安装 PyTorch 可能会更加简单和高效。
conda install pytorch torchvision -c pytorch
如果不了解Anaconda,可以参考: Anaconda 教程
通过 PyTorch 官网安装
访问 PyTorch 的官方网站 Get Started,网站提供了一个方便的工具,可以根据你的系统配置(操作系统、包管理器、Python版本以及CUDA版本)推荐安装命令。
从源代码安装
如果你需要从源代码安装PyTorch,或者想要尝试最新的开发版本,你可以使用以下命令:
git clone --recursive https://github.com/pytorch/pytorch cd pytorch python setup.py install
这将从 GitHub 克隆 PyTorch 的源代码,并使用 setup.py 进行安装。
验证安装
为了确保 PyTorch 已正确安装,我们可以通过执行以下 PyTorch 代码来验证是否安装成功:
实例
import torch
# 当前安装的 PyTorch 库的版本
print(torch.__version__)
# 检查 CUDA 是否可用,即你的系统有 NVIDIA 的 GPU
print(torch.cuda.is_available())
如果 torch.cuda.is_available() 输出 True,则说明 PyTorch 成功识别到你的 GPU。
一个简单的实例,构建一个随机初始化的张量:
实例
import torch
x = torch.rand(5, 3)
print(x)
如果安装成功,输出结果类似如下:
tensor([[0.3380, 0.3845, 0.3217], [0.8337, 0.9050, 0.2650], [0.2979, 0.7141, 0.9069], [0.1449, 0.1132, 0.1375], [0.4675, 0.3947, 0.1426]])
PyTorch 基础
PyTorch 主要有以下几个基础概念:张量(Tensor)、自动求导(Autograd)、神经网络模块(nn.Module)、优化器(optim)等。
- 张量(Tensor):PyTorch 的核心数据结构,支持多维数组,并可以在 CPU 或 GPU 上进行加速计算。
- 自动求导(Autograd):PyTorch 提供了自动求导功能,可以轻松计算模型的梯度,便于进行反向传播和优化。
- 神经网络(nn.Module):PyTorch 提供了简单且强大的 API 来构建神经网络模型,可以方便地进行前向传播和模型定义。
- 优化器(Optimizers):使用优化器(如 Adam、SGD 等)来更新模型的参数,使得损失最小化。
- 设备(Device):可以将模型和张量移动到 GPU 上以加速计算。
张量(Tensor)
张量(Tensor)是 PyTorch 中的核心数据结构,用于存储和操作多维数组。
张量可以视为一个多维数组,支持加速计算的操作。
在 PyTorch 中,张量的概念类似于 NumPy 中的数组,但是 PyTorch 的张量可以运行在不同的设备上,比如 CPU 和 GPU,这使得它们非常适合于进行大规模并行计算,特别是在深度学习领域。
-
维度(Dimensionality):张量的维度指的是数据的多维数组结构。例如,一个标量(0维张量)是一个单独的数字,一个向量(1维张量)是一个一维数组,一个矩阵(2维张量)是一个二维数组,以此类推。
-
形状(Shape):张量的形状是指每个维度上的大小。例如,一个形状为
(3, 4)
的张量意味着它有3行4列。 -
数据类型(Dtype):张量中的数据类型定义了存储每个元素所需的内存大小和解释方式。PyTorch支持多种数据类型,包括整数型(如
torch.int8
、torch.int32
)、浮点型(如torch.float32
、torch.float64
)和布尔型(torch.bool
)。
张量创建:
实例
import torch
# 创建一个 2x3 的全 0 张量
a = torch.zeros(2, 3)
print(a)
# 创建一个 2x3 的全 1 张量
b = torch.ones(2, 3)
print(b)
# 创建一个 2x3 的随机数张量
c = torch.randn(2, 3)
print(c)
# 从 NumPy 数组创建张量
import numpy as np
numpy_array = np.array([[1, 2], [3, 4]])
tensor_from_numpy = torch.from_numpy(numpy_array)
print(tensor_from_numpy)
# 在指定设备(CPU/GPU)上创建张量
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
d = torch.randn(2, 3, device=device)
print(d)输出结果类似如下:
tensor([[0., 0., 0.], [0., 0., 0.]]) tensor([[1., 1., 1.], [1., 1., 1.]]) tensor([[ 1.0189, -0.5718, -1.2814], [-0.5865, 1.0855, 1.1727]]) tensor([[1, 2], [3, 4]]) tensor([[-0.3360, 0.2203, 1.3463], [-0.5982, -0.2704, 0.5429]])
常用张量操作:
实例
# 张量相加
e = torch.randn(2, 3)
f = torch.randn(2, 3)
print(e + f)
# 逐元素乘法
print(e * f)
# 张量的转置
g = torch.randn(3, 2)
print(g.t()) # 或者 g.transpose(0, 1)
# 张量的形状
print(g.shape) # 返回形状
张量与设备
PyTorch 张量可以存在于不同的设备上,包括CPU和GPU,你可以将张量移动到 GPU 上以加速计算:
if torch.cuda.is_available(): tensor_gpu = tensor_from_list.to('cuda') # 将张量移动到GPU
梯度和自动微分
PyTorch的张量支持自动微分,这是深度学习中的关键特性。当你创建一个需要梯度的张量时,PyTorch可以自动计算其梯度:
实例
# 创建一个需要梯度的张量
tensor_requires_grad = torch.tensor([1.0], requires_grad=True)
# 进行一些操作
tensor_result = tensor_requires_grad * 2
# 计算梯度
tensor_result.backward()
print(tensor_requires_grad.grad) # 输出梯度
内存和性能
PyTorch 张量还提供了一些内存管理功能,比如.clone()、.detach() 和 .to() 方法,它们可以帮助你优化内存使用和提高性能。
自动求导(Autograd)
自动求导(Automatic Differentiation,简称Autograd)是深度学习框架中的一个核心特性,它允许计算机自动计算数学函数的导数。
在深度学习中,自动求导主要用于两个方面:一是在训练神经网络时计算梯度,二是进行反向传播算法的实现。
自动求导基于链式法则(Chain Rule),这是一个用于计算复杂函数导数的数学法则。链式法则表明,复合函数的导数是其各个组成部分导数的乘积。在深度学习中,模型通常是由许多层组成的复杂函数,自动求导能够高效地计算这些层的梯度。
动态图与静态图:
-
动态图(Dynamic Graph):在动态图中,计算图在运行时动态构建。每次执行操作时,计算图都会更新,这使得调试和修改模型变得更加容易。PyTorch使用的是动态图。
-
静态图(Static Graph):在静态图中,计算图在开始执行之前构建完成,并且不会改变。TensorFlow最初使用的是静态图,但后来也支持动态图。
PyTorch 提供了自动求导功能,通过 autograd 模块来自动计算梯度。
torch.Tensor 对象有一个 requires_grad 属性,用于指示是否需要计算该张量的梯度。
当你创建一个 requires_grad=True 的张量时,PyTorch 会自动跟踪所有对它的操作,以便在之后计算梯度。
创建需要梯度的张量:
实例
# 创建一个需要计算梯度的张量
x = torch.randn(2, 2, requires_grad=True)
print(x)
# 执行某些操作
y = x + 2
z = y * y * 3
out = z.mean()
print(out)
输出结果类似如下:
tensor([[0., 0., 0.], [0., 0., 0.]]) tensor([[1., 1., 1.], [1., 1., 1.]]) tensor([[ 1.0189, -0.5718, -1.2814], [-0.5865, 1.0855, 1.1727]]) tensor([[1, 2], [3, 4]]) tensor([[-0.3360, 0.2203, 1.3463], [-0.5982, -0.2704, 0.5429]]) tianqixin@Mac-mini runoob-test % python3 test.py tensor([[-0.1908, 0.2811], [ 0.8068, 0.8002]], requires_grad=True) tensor(18.1469, grad_fn=<MeanBackward0>)
反向传播(Backpropagation)
一旦定义了计算图,可以通过 .backward() 方法来计算梯度。
实例
# 反向传播,计算梯度
out.backward()
# 查看 x 的梯度
print(x.grad)
在神经网络训练中,自动求导主要用于实现反向传播算法。
反向传播是一种通过计算损失函数关于网络参数的梯度来训练神经网络的方法。在每次迭代中,网络的前向传播会计算输出和损失,然后反向传播会计算损失关于每个参数的梯度,并使用这些梯度来更新参数。
停止梯度计算
如果你不希望某些张量的梯度被计算(例如,当你不需要反向传播时),可以使用 torch.no_grad() 或设置 requires_grad=False。
实例
# 使用 torch.no_grad() 禁用梯度计算
with torch.no_grad():
y = x * 2
神经网络(nn.Module)
神经网络是一种模仿人脑神经元连接的计算模型,由多层节点(神经元)组成,用于学习数据之间的复杂模式和关系。
神经网络通过调整神经元之间的连接权重来优化预测结果,这一过程涉及前向传播、损失计算、反向传播和参数更新。
神经网络的类型包括前馈神经网络、卷积神经网络(CNN)、循环神经网络(RNN)和长短期记忆网络(LSTM),它们在图像识别、语音处理、自然语言处理等多个领域都有广泛应用。
PyTorch 提供了一个非常方便的接口来构建神经网络模型,即 torch.nn.Module。
我们可以继承 nn.Module 类并定义自己的网络层。
创建一个简单的神经网络:
实例
import torch.nn as nn
import torch.optim as optim
# 定义一个简单的全连接神经网络
class SimpleNN(nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(2, 2) # 输入层到隐藏层
self.fc2 = nn.Linear(2, 1) # 隐藏层到输出层
def forward(self, x):
x = torch.relu(self.fc1(x)) # ReLU 激活函数
x = self.fc2(x)
return x
# 创建网络实例
model = SimpleNN()
# 打印模型结构
print(model)
输出结果:
SimpleNN( (fc1): Linear(in_features=2, out_features=2, bias=True) (fc2): Linear(in_features=2, out_features=1, bias=True) )
训练过程:
-
前向传播(Forward Propagation): 在前向传播阶段,输入数据通过网络层传递,每层应用权重和激活函数,直到产生输出。
-
计算损失(Calculate Loss): 根据网络的输出和真实标签,计算损失函数的值。
-
反向传播(Backpropagation): 反向传播利用自动求导技术计算损失函数关于每个参数的梯度。
-
参数更新(Parameter Update): 使用优化器根据梯度更新网络的权重和偏置。
-
迭代(Iteration): 重复上述过程,直到模型在训练数据上的性能达到满意的水平。
前向传播与损失计算
实例
# 随机输入
x = torch.randn(1, 2)
# 前向传播
output = model(x)
print(output)
# 定义损失函数(例如均方误差 MSE)
criterion = nn.MSELoss()
# 假设目标值为 1
target = torch.randn(1, 1)
# 计算损失
loss = criterion(output, target)
print(loss)
优化器(Optimizers)
优化器在训练过程中更新神经网络的参数,以减少损失函数的值。
PyTorch 提供了多种优化器,例如 SGD、Adam 等。
使用优化器进行参数更新:
实例
# 定义优化器(使用 Adam 优化器)
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练步骤
optimizer.zero_grad() # 清空梯度
loss.backward() # 反向传播
optimizer.step() # 更新参数
训练模型
训练模型是机器学习和深度学习中的核心过程,旨在通过大量数据学习模型参数,以便模型能够对新的、未见过的数据做出准确的预测。
训练模型通常包括以下几个步骤:
-
数据准备:
- 收集和处理数据,包括清洗、标准化和归一化。
- 将数据分为训练集、验证集和测试集。
-
定义模型:
- 选择模型架构,例如决策树、神经网络等。
- 初始化模型参数(权重和偏置)。
-
选择损失函数:
- 根据任务类型(如分类、回归)选择合适的损失函数。
-
选择优化器:
- 选择一个优化算法,如SGD、Adam等,来更新模型参数。
-
前向传播:
- 在每次迭代中,将输入数据通过模型传递,计算预测输出。
-
计算损失:
- 使用损失函数评估预测输出与真实标签之间的差异。
-
反向传播:
- 利用自动求导计算损失相对于模型参数的梯度。
-
参数更新:
- 根据计算出的梯度和优化器的策略更新模型参数。
-
迭代优化:
- 重复步骤5-8,直到模型在验证集上的性能不再提升或达到预定的迭代次数。
-
评估和测试:
- 使用测试集评估模型的最终性能,确保模型没有过拟合。
-
模型调优:
- 根据模型在测试集上的表现进行调参,如改变学习率、增加正则化等。
-
部署模型:
- 将训练好的模型部署到生产环境中,用于实际的预测任务。
实例
import torch
import torch.nn as nn
import torch.optim as optim
# 1. 定义一个简单的神经网络模型
class SimpleNN(nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(2, 2) # 输入层到隐藏层
self.fc2 = nn.Linear(2, 1) # 隐藏层到输出层
def forward(self, x):
x = torch.relu(self.fc1(x)) # ReLU 激活函数
x = self.fc2(x)
return x
# 2. 创建模型实例
model = SimpleNN()
# 3. 定义损失函数和优化器
criterion = nn.MSELoss() # 均方误差损失函数
optimizer = optim.Adam(model.parameters(), lr=0.001) # Adam 优化器
# 4. 假设我们有训练数据 X 和 Y
X = torch.randn(10, 2) # 10 个样本,2 个特征
Y = torch.randn(10, 1) # 10 个目标值
# 5. 训练循环
for epoch in range(100): # 训练 100 轮
optimizer.zero_grad() # 清空之前的梯度
output = model(X) # 前向传播
loss = criterion(output, Y) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
# 每 10 轮输出一次损失
if (epoch+1) % 10 == 0:
print(f'Epoch [{epoch+1}/100], Loss: {loss.item():.4f}')
输出结果如下:
Epoch [10/100], Loss: 1.7180 Epoch [20/100], Loss: 1.6352 Epoch [30/100], Loss: 1.5590 Epoch [40/100], Loss: 1.4896 Epoch [50/100], Loss: 1.4268 Epoch [60/100], Loss: 1.3704 Epoch [70/100], Loss: 1.3198 Epoch [80/100], Loss: 1.2747 Epoch [90/100], Loss: 1.2346 Epoch [100/100], Loss: 1.1991
在每 10 轮,程序会输出当前的损失值,帮助我们跟踪模型的训练进度。随着训练的进行,损失值应该会逐渐降低,表示模型在不断学习并优化其参数。
训练模型是一个迭代的过程,需要不断地调整和优化,直到达到满意的性能。这个过程涉及到大量的实验和调优,目的是使模型在新的、未见过的数据上也能有良好的泛化能力。
设备(Device)
PyTorch 允许你将模型和数据移动到 GPU 上进行加速。
使用 torch.device 来指定计算设备。
将模型和数据移至 GPU:
实例
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 将模型移动到设备
model.to(device)
# 将数据移动到设备
X = X.to(device)
Y = Y.to(device)
在训练过程中,所有张量和模型都应该移到同一个设备上(要么都在 CPU 上,要么都在 GPU 上)。