PyTorch:深度学习的 powerful 库
PyTorch 是目前最流行的深度学习框架之一,它具有易用性、灵活性和强大的社区支持。本文将深入探讨 PyTorch 的基本概念、核心组件和实际应用,帮助你快速上手 PyTorch。
目录
一、PyTorch 简介
(一)动态计算图
(二)张量(Tensor)操作
(三)自动求导(Autograd)
(四)丰富的预训练模型和工具库
(五)活跃的社区和生态系统
二、PyTorch 的安装与配置
(一)环境准备
(二)安装 PyTorch
(三)验证安装
三、PyTorch 基本数据类型:张量(Tensor)
(一)创建张量
1. 从列表创建张量
2. 基于现有张量创建张量
3. 创建具有特定形状和值的张量
(二)张量的基本操作
1. 索引与切片
2. 形状变换
3. 拼接张量
4. 拆分张量
(三)张量的运算
1. 基本数学运算
2. 矩阵运算
3. 统计运算
4. 自动求导
四、VS Code 配置 PyTorch
(一)安装 VS Code
(二)安装 Python 插件
(三)配置 Python 解释器
(四)验证 PyTorch 配置
(五)VS Code 配置 Python 环境的其他建议
五、基于 PyTorch 实现神经网络算法
(一)数据准备
(二)定义神经网络模型
(三)定义损失函数和优化器
(四)训练模型
(五)测试模型
六、PyTorch 在实际应用中的案例
(一)计算机视觉:图像分类
(二)自然语言处理:文本分类
一、PyTorch 简介
PyTorch 是一个开源的机器学习库,由 Facebook 的 AI 研究实验室(FAIR)开发并于 2016 年发布。它基于 Torch(一个早期的机器学习库)构建,旨在提供更强大的功能和灵活性,同时简化深度学习模型的构建和训练过程。
PyTorch 的主要特点如下:
(一)动态计算图
与一些静态计算图的深度学习框架(如 TensorFlow 早期版本)不同,PyTorch 采用动态计算图机制。动态计算图允许我们在运行时构建和修改计算图,提供了更大的灵活性,特别是在处理变长序列或复杂网络结构时。这种动态性使得调试更加方便,代码也更易于理解和修改。
(二)张量(Tensor)操作
PyTorch 的核心数据结构是张量(Tensor),它类似于 NumPy 的 ndarray,但具有额外的功能,如 GPU 加速计算。张量可以表示多维数组,是深度学习中数据表示和模型参数的基础。
(三)自动求导(Autograd)
自动求导是深度学习框架中的关键技术,PyTorch 提供了强大的自动求导机制。在构建计算图的过程中,PyTorch 会自动记录张量的操作,从而能够自动计算梯度,大大简化了模型训练过程中的反向传播步骤。
(四)丰富的预训练模型和工具库
PyTorch 拥有丰富的预训练模型库(如 TorchVision、TorchText、TorchAudio 等),这些模型可以直接用于实际应用或作为迁移学习的基础。此外,PyTorch 还提供了各种工具库和接口,方便与深度学习的其他组件(如分布式训练、量化等)集成。
(五)活跃的社区和生态系统
PyTorch 拥有一个庞大而活跃的社区,这意味着你可以轻松找到大量的教程、示例代码和解决方案来帮助你解决问题。社区的活跃性也促进了 PyTorch 的快速发展和更新,不断引入新的功能和改进。
二、PyTorch 的安装与配置
(一)环境准备
在开始使用 PyTorch 之前,确保你的开发环境已正确配置。PyTorch 支持多种操作系统,包括 Windows、Linux 和 macOS。对于深度学习任务,建议使用安装了 NVIDIA GPU 的系统,并确保已安装兼容的 CUDA Toolkit,以充分利用 GPU 加速计算。
(二)安装 PyTorch
你可以通过多种方式安装 PyTorch,包括使用 pip、conda 或从源代码编译。以下是使用 pip 安装 PyTorch 的示例:
pip install torch torchvision torchaudio
对于使用 conda 的用户:
conda install pytorch torchvision torchaudio -c pytorch
在安装过程中,PyTorch 会自动选择适合你系统环境的版本。如果你想安装特定版本或为 CPU 优化的版本,可以在安装命令中添加相应的参数。
(三)验证安装
安装完成后,可以通过以下 Python 代码验证 PyTorch 是否正确安装:
import torch
print(torch.__version__)
print(torch.cuda.is_available()) # 检查 GPU 是否可用
如果输出了 PyTorch 的版本号,并且在有 GPU 环境下 torch.cuda.is_available()
返回 True
,则说明 PyTorch 已成功安装。
三、PyTorch 基本数据类型:张量(Tensor)
张量是 PyTorch 中最基本的数据类型,类似于 NumPy 的多维数组。张量可以用于表示各种维度的数据,从标量(0 维张量)到向量(1 维张量)、矩阵(2 维张量)以及更高维的数据。
(一)创建张量
你可以通过多种方式创建张量:
1. 从列表创建张量
import torch# 创建标量
scalar = torch.tensor(5)
print(scalar)
print(scalar.dim()) # 输出张量的维度数# 创建向量
vector = torch.tensor([1, 2, 3, 4])
print(vector)
print(vector.dim())# 创建矩阵
matrix = torch.tensor([[1, 2], [3, 4]])
print(matrix)
print(matrix.dim())# 创建 3 维张量
tensor_3d = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(tensor_3d)
print(tensor_3d.dim())
tensor(5)
0
tensor([1, 2, 3, 4])
1
tensor([[1, 2],[3, 4]])
2
tensor([[[1, 2],[3, 4]],[[5, 6],[7, 8]]])
3
2. 基于现有张量创建张量
import torch# 基于现有张量创建新的张量
existing_tensor = torch.tensor([1, 2, 3])
new_tensor = torch.tensor(existing_tensor)
print(new_tensor)# 使用 ones_like 创建全 1 张量
ones_tensor = torch.ones_like(existing_tensor)
print(ones_tensor)# 使用 zeros_like 创建全 0 张量
zeros_tensor = torch.zeros_like(existing_tensor)
print(zeros_tensor)
输出结果:
tensor([1, 2, 3])
tensor([1., 1., 1.])
tensor([0., 0., 0.])
3. 创建具有特定形状和值的张量
import torch# 创建全 1 张量
ones_tensor = torch.ones(2, 3)
print(ones_tensor)# 创建全 0 张量
zeros_tensor = torch.zeros(2, 3)
print(zeros_tensor)# 创建随机张量
random_tensor = torch.rand(2, 3)
print(random_tensor)# 创建指定值的张量
filled_tensor = torch.full((2, 3), 7)
print(filled_tensor)
输出结果:
tensor([[1., 1., 1.],[1., 1., 1.]])
tensor([[0., 0., 0.],[0., 0., 0.]])
tensor([[0.5305, 0.2182, 0.9925],[0.6698, 0.3397, 0.6080]])
tensor([[7, 7, 7],[7, 7, 7]])
(二)张量的基本操作
张量的基本操作包括索引、切片、形状变换、转置、拼接等。
1. 索引与切片
import torchtensor = torch.tensor([[1, 2, 3], [4, 5, 6]])# 索引访问元素
print(tensor[0, 1]) # 输出 2# 切片操作
print(tensor[0, :]) # 输出 tensor([1, 2, 3])
print(tensor[:, 1]) # 输出 tensor([2, 5])
print(tensor[0:2, 0:2]) # 输出 tensor([[1, 2], [4, 5]])
2. 形状变换
import torchtensor = torch.tensor([[1, 2, 3], [4, 5, 6]])# 查看张量形状
print(tensor.shape) # 输出 torch.Size([2, 3])# 改变张量形状
reshaped_tensor = tensor.view(3, 2)
print(reshaped_tensor)
print(reshaped_tensor.shape) # 输出 torch.Size([3, 2])# 转置张量
transposed_tensor = tensor.t()
print(transposed_tensor)
print(transposed_tensor.shape) # 输出 torch.Size([3, 2])
3. 拼接张量
import torchtensor1 = torch.tensor([[1, 2], [3, 4]])
tensor2 = torch.tensor([[5, 6], [7, 8]])# 按维度 0 拼接
concatenated_tensor_row = torch.cat((tensor1, tensor2), dim=0)
print(concatenated_tensor_row)# 按维度 1 拼接
concatenated_tensor_col = torch.cat((tensor1, tensor2), dim=1)
print(concatenated_tensor_col)
tensor([[1, 2],[3, 4],[5, 6],[7, 8]])
tensor([[1, 2, 5, 6],[3, 4, 7, 8]])
4. 拆分张量
import torchtensor = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]])# 按维度 1 拆分,分成两个大小为 2 的张量
split_tensors = torch.split(tensor, split_size_or_sections=2, dim=1)
for split_tensor in split_tensors:print(split_tensor)
tensor([[1, 2],[5, 6]])
tensor([[3, 4],[7, 8]])
(三)张量的运算
PyTorch 提供了丰富的张量运算功能,包括基本数学运算、矩阵运算、统计运算等。
1. 基本数学运算
import torchtensor1 = torch.tensor([1, 2, 3])
tensor2 = torch.tensor([4, 5, 6])# 加法
add_result = tensor1 + tensor2
print(add_result) # 输出 tensor([5, 7, 9])# 减法
sub_result = tensor1 - tensor2
print(sub_result) # 输出 tensor([-3, -3, -3])# 乘法
mul_result = tensor1 * tensor2
print(mul_result) # 输出 tensor([4, 10, 18])# 除法
div_result = tensor1 / tensor2
print(div_result) # 输出 tensor([0.2500, 0.4000, 0.5000])
2. 矩阵运算
import torchmatrix1 = torch.tensor([[1, 2], [3, 4]])
matrix2 = torch.tensor([[5, 6], [7, 8]])# 矩阵乘法
matrix_product = torch.matmul(matrix1, matrix2)
print(matrix_product)
tensor([[19, 22],[43, 50]])
3. 统计运算
import torchtensor = torch.tensor([1, 2, 3, 4, 5])# 计算均值
mean_value = torch.mean(tensor.float()) # 注意:mean 需要 float 类型
print(mean_value) # 输出 tensor(3.)# 计算中位数
median_value = torch.median(tensor)
print(median_value) # 输出 tensor(3)# 计算最大值
max_value = torch.max(tensor)
print(max_value) # 输出 tensor(5)# 计算最小值
min_value = torch.min(tensor)
print(min_value) # 输出 tensor(1)
4. 自动求导
import torch# 创建需要跟踪梯度的张量
x = torch.tensor(2.0, requires_grad=True)# 构建计算图
y = x ** 3
z = y + 2# 反向传播计算梯度
z.backward()# 查看梯度
print(x.grad) # 输出 tensor(12.),即 dz/dx = 3x^2 = 12
四、VS Code 配置 PyTorch
Visual Studio Code(VS Code) 是一个流行的代码编辑器,它具有丰富的插件生态系统和良好的 Python 支持。以下是配置 VS Code 以使用 PyTorch 的基本步骤:
(一)安装 VS Code
从官方网站(Visual Studio Code - Code Editing. Redefined)下载并安装适合你操作系统的 VS Code 版本。
(二)安装 Python 插件
-
打开 VS Code。
-
点击左侧活动栏中的扩展视图图标(或按
Ctrl+Shift+X
)。 -
搜索内容为 “Python”,然后点击搜索结果中的 “Python” 插件(由 Microsoft 提供)进行安装。
(三)配置 Python 解释器
-
打开 VS Code 的命令面板(按
Ctrl+Shift+P
)。 -
输入 “Python:选择解释器”,然后选择你已安装的包含 PyTorch 的 Python 解释器。这通常是通过
pip
或conda
安装 PyTorch 时所使用的 Python 环境。
(四)验证 PyTorch 配置
创建一个新的 Python 文件(例如 test_pytorch.py
),输入以下代码:
import torch
print(torch.__version__)
print(torch.cuda.is_available())
然后运行此脚本(可以按 F5
或右键点击编辑器中的脚本并选择 “运行 Python 文件”)。如果输出了 PyTorch 的版本号,并且在有 GPU 环境下 torch.cuda.is_available()
返回 True
,则说明 VS Code 已正确配置 PyTorch。
(五)VS Code 配置 Python 环境的其他建议
为了更高效地使用 VS Code 进行 Python 和 PyTorch 开发,你可以考虑以下配置:
-
设置工作区解释器 :你可以在 VS Code 的工作区设置中指定一个特定的 Python 解释器,这样可以确保所有与该工作区相关的任务都使用相同的环境。
-
使用虚拟环境 :创建和使用虚拟环境是一种良好的实践,它可以避免不同项目之间的依赖冲突。在 VS Code 中,你可以轻松创建和管理虚拟环境,并为每个项目指定不同的虚拟环境。
-
安装其他有用的插件 :例如,Jupyter 插件可以在 VS Code 中直接运行 Jupyter Notebook,这对于交互式数据科学工作很有用。此外,Pylance 插件提供了更高级的 Python 语言支持,包括类型检查和代码补全。
五、基于 PyTorch 实现神经网络算法
现在,让我们通过一个简单的示例来了解如何基于 PyTorch 实现神经网络算法。我们将构建一个简单的多层感知机(MLP),用于对鸢尾花数据集(Iris dataset)进行分类。
(一)数据准备
首先,加载和准备数据:
import torch
import torchvision
from torchvision.datasets import Iris
from torch.utils.data import DataLoader, TensorDataset# 加载数据
transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()
])train_dataset = Iris(root='./data', train=True, download=True, transform=transform)
test_dataset = Iris(root='./data', train=False, transform=transform)# 创建数据加载器
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
(二)定义神经网络模型
import torch.nn as nn
import torch.nn.functional as Fclass MLP(nn.Module):def __init__(self):super(MLP, self).__init__()self.fc1 = nn.Linear(4, 128) # 输入层到隐藏层self.fc2 = nn.Linear(128, 64) # 隐藏层到隐藏层self.fc3 = nn.Linear(64, 3) # 隐藏层到输出层def forward(self, x):x = F.relu(self.fc1(x)) # 使用 ReLU 激活函数x = F.relu(self.fc2(x))x = self.fc3(x)return xmodel = MLP()
(三)定义损失函数和优化器
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
(四)训练模型
# 训练模型
num_epochs = 10for epoch in range(num_epochs):model.train() # 设置模型为训练模式for batch_idx, (data, target) in enumerate(train_loader):# 前向传播output = model(data)loss = criterion(output, target)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()# 打印训练信息if (batch_idx + 1) % 10 == 0:print(f'Epoch [{epoch+1}/{num_epochs}], Batch [{batch_idx+1}/{len(train_loader)}], Loss: {loss.item():.4f}')
(五)测试模型
# 测试模型
model.eval() # 设置模型为评估模式
correct = 0
total = 0with torch.no_grad():for data, target in test_loader:output = model(data)_, predicted = torch.max(output.data, 1)total += target.size(0)correct += (predicted == target).sum().item()print(f'Test Accuracy: {100 * correct / total:.2f}%')
六、PyTorch 在实际应用中的案例
(一)计算机视觉:图像分类
在计算机视觉领域,PyTorch 提供了丰富的预训练模型和工具,用于图像分类任务。以下是一个使用 PyTorch 进行图像分类的简单示例:
import torch
import torchvision
import torchvision.transforms as transforms# 加载和预处理数据
transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True)test_dataset = torchvision.datasets.CIFAR10(root='./data', train=False, transform=transform)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False)# 加载预训练模型
model = torchvision.models.resnet18(pretrained=True)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 10) # 修改输出层以适应 CIFAR-10 数据集# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# 训练模型
num_epochs = 10for epoch in range(num_epochs):model.train()for batch_idx, (data, target) in enumerate(train_loader):output = model(data)loss = criterion(output, target)optimizer.zero_grad()loss.backward()optimizer.step()if (batch_idx + 1) % 10 == 0:print(f'Epoch [{epoch+1}/{num_epochs}], Batch [{batch_idx+1}/{len(train_loader)}], Loss: {loss.item():.4f}')# 测试模型
model.eval()
correct = 0
total = 0with torch.no_grad():for data, target in test_loader:output = model(data)_, predicted = torch.max(output.data, 1)total += target.size(0)correct += (predicted == target).sum().item()print(f'Test Accuracy: {100 * correct / total:.2f}%')
(二)自然语言处理:文本分类
在自然语言处理领域,PyTorch 可以用于各种任务,如文本分类、机器翻译、情感分析等。以下是一个使用 PyTorch 进行文本分类的简单示例:
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchtext.datasets import IMDB
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator# 加载数据
train_dataset = IMDB(split='train')
test_dataset = IMDB(split='test')# 文本预处理
tokenizer = get_tokenizer('basic_english')
def yield_tokens(data_iter):for _, text in data_iter:yield tokenizer(text)vocab = build_vocab_from_iterator(yield_tokens(train_dataset), specials=['<unk>'])
vocab.set_default_index(vocab['<unk>'])# 将文本转换为张量
def text_pipeline(text):return vocab(tokenizer(text))def label_pipeline(label):return 1 if label == 'pos' else 0# 创建数据加载器
from torch.utils.data.dataset import random_split
from torchtext.data.functional import to_map_style_datasettrain_dataset = to_map_style_dataset(train_dataset)
test_dataset = to_map_style_dataset(test_dataset)num_train = int(len(train_dataset) * 0.95)
split_train_, split_valid_ = random_split(train_dataset, [num_train, len(train_dataset) - num_train])def collate_batch(batch):label_list, text_list = [], []for (_label, _text) in batch:label_list.append(label_pipeline(_label))processed_text = torch.tensor(text_pipeline(_text), dtype=torch.int64)text_list.append(processed_text)label_list = torch.tensor(label_list, dtype=torch.int64)text_list = torch.nn.utils.rnn.pad_sequence(text_list, padding_value=0)return label_list, text_listtrain_loader = torch.utils.data.DataLoader(split_train_, batch_size=32, collate_fn=collate_batch)
valid_loader = torch.utils.data.DataLoader(split_valid_, batch_size=32, collate_fn=collate_batch)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, collate_fn=collate_batch)# 定义神经网络模型
class TextClassificationModel(nn.Module):def __init__(self, vocab_size, embed_dim, num_class):super(TextClassificationModel, self).__init__()self.embedding = nn.EmbeddingBag(vocab_size, embed_dim, sparse=True)self.fc = nn.Linear(embed_dim, num_class)def forward(self, text):embedded = self.embedding(text)return self.fc(embedded)vocab_size = len(vocab)
embed_dim = 64
num_class = 2model = TextClassificationModel(vocab_size, embed_dim, num_class)# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 10for epoch in range(num_epochs):model.train()for batch_idx, (label, text) in enumerate(train_loader):output = model(text)loss = criterion(output, label)optimizer.zero_grad()loss.backward()optimizer.step()if (batch_idx + 1) % 10 == 0:print(f'Epoch [{epoch+1}/{num_epochs}], Batch [{batch_idx+1}/{len(train_loader)}], Loss: {loss.item():.4f}')# 测试模型
model.eval()
correct = 0
total = 0with torch.no_grad():for label, text in test_loader:output = model(text)_, predicted = torch.max(output.data, 1)total += label.size(0)correct += (predicted == label).sum().item()print(f'Test Accuracy: {100 * correct / total:.2f}%')