💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
- 推荐:「stormsha的主页」👈,持续学习,不断总结,共同进步,为了踏实,做好当下事儿~
- 专栏导航
- Python面试合集系列:Python面试题合集,剑指大厂
- GO基础学习笔记系列:记录博主学习GO语言的笔记,该笔记专栏尽量写的试用所有入门GO语言的初学者
- 数据库系列:详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
- 运维系列:总结好用的命令,高效开发
- 算法与数据结构系列:总结数据结构和算法,不同类型针对性训练,提升编程思维
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
💖The Start💖点点关注,收藏不迷路💖 |
📒文章目录
- 1、张量(Tensors)
- 1.1、创建张量
- 1.1.1、创建无初始化张量
- 1.1.2、创建随机张量
- 1.1.3、创建初值为指定数值的张量
- 1.1.4、从数据创建张量
- 1.1.5、生成等差数列张量
- 1.2、改变张量形状
- 1.3、张量操作
- 1.4、张量属性
- 2、自动微分(Autograd)
- 2.1、自动微分的工作原理
- 2.2、停止梯度追踪
- 2.3、禁用梯度计算
- 3、神经网络模块(nn.Module)
- 3.1、定义神经网络
- 3.1.1、 `__init__`方法
- 3.1.2、`forward`方法
- 3.2、使用神经网络
- 4、优化器(Optimizer)
- 4.1、优化器的使用
- 4.2、参数组(param_groups)
- 4.3、学习率调整
- 5、数据加载器(DataLoader)
- 5.1、Dataset类
- 5.2、DataLoader类
- 5.3、使用DataLoader进行数据迭代
- 6、损失函数(Loss Function)
- 6.1、损失函数的类型
- 6.2、使用损失函数
- 6.3、自定义损失函数
PyTorch作为一款强大的深度学习框架,具备易用性和高度灵活性,尤其受到研究者和开发者们的青睐,原因在于其提供了以下核心概念及功能
1、张量(Tensors)
-
张量是PyTorch中多维数组的数据结构,与NumPy数组类似,但额外支持GPU加速计算和自动微分功能。
-
维度和秩(Rank):张量可以有任意数量的维度,比如标量(0-D)、向量(1-D)、矩阵(2-D)等。
-
数据类型(Data Types):支持多种数据类型,包括但不限于浮点数、整数和布尔值,可以通过指定类型创建张量。
-
创建方式:可通过
torch.tensor()
、torch.zeros()
、torch.ones()
等函数创建张量,也可以从NumPy数组转换而来。 -
操作:提供丰富的数学运算、形状操作、索引和切片等方法,便于数据处理和转换。
-
设备和内存管理:张量可以在CPU或GPU上存储和计算,可以灵活地在两者间移动。
下面将详细介绍张量的创建、操作和属性。
1.1、创建张量
1.1.1、创建无初始化张量
使用torch.empty()
函数可以创建一个未初始化内存的张量,例如:
import torch
x = torch.empty(3, 4) # 创建一个形状为(3, 4)的未初始化张量
1.1.2、创建随机张量
使用torch.rand()
函数可以创建一个服从0到1之间均匀分布的随机张量,例如:
x = torch.rand(3, 4) # 创建一个形状为(3, 4)的随机张量
使用torch.randn()
函数可以创建一个服从标准正态分布的随机张量,例如:
x = torch.randn(3, 4) # 创建一个形状为(3, 4)的随机张量,服从标准正态分布
使用torch.rand_like()
函数可以创建一个与给定张量形状相同的随机张量,例如:
y = torch.rand(2, 3)
x = torch.rand_like(y) # 创建一个与y形状相同的随机张量
使用torch.randint()
函数可以创建一个指定范围内的随机整数张量,例如:
x = torch.randint(1, 10, [3, 3]) # 创建一个形状为(3, 3)的随机整数张量,元素取值范围为[1, 10)
1.1.3、创建初值为指定数值的张量
使用torch.zeros()
函数可以创建一个初值全为0的张量,例如:
x = torch.zeros(3, 4) # 创建一个形状为(3, 4)的初值全为0的张量
使用torch.full()
函数可以创建一个初值全为指定值的张量,例如:
x = torch.full([3, 4], 6) # 创建一个形状为(3, 4)的初值全为6的张量
使用torch.eye()
函数可以创建一个单位矩阵,例如:
x = torch.eye(5, 5) # 创建一个形状为(5, 5)的单位矩阵
1.1.4、从数据创建张量
使用torch.tensor()
函数可以从Python列表或NumPy数组创建张量,例如:
data = [[1, 2, 3], [4, 5, 6]]
x = torch.tensor(data) # 从Python列表创建张量
1.1.5、生成等差数列张量
使用torch.arange()
函数可以生成等差数列张量,例如:
x = torch.arange(0, 10) # 生成从0到9的等差数列张量
1.2、改变张量形状
使用view()
或reshape()
方法可以改变张量的形状,它们的功能和用法是相同的。例如:
a = torch.tensor([1, 2, 3, 4, 5, 6, 7, 8])
b = a.view(2, 4) # 将a重塑为形状为(2, 4)的张量
c = a.reshape(2, 4) # 将a重塑为形状为(2, 4)的张量
1.3、张量操作
PyTorch提供了丰富的张量操作函数,例如加法、减法、乘法等。例如:
x = torch.tensor([1, 2, 3])
y = torch.tensor([4, 5, 6])
z = x + y # 张量加法
1.4、张量属性
每个张量都有一些属性,例如形状(shape)、大小(size)和数据类型(dtype)。可以使用以下方法获取这些属性:
x = torch.tensor([1, 2, 3])
x.shape # 获取张量的形状
x.size() # 获取张量的大小
x.dtype # 获取张量的数据类型
2、自动微分(Autograd)
- PyTorch的核心特性之一,用于计算复合函数的梯度。
- 支持动态计算图,根据实际代码执行动态构建和优化计算路径。
- 通过
.requires_grad=True
开启张量的梯度追踪,进而能自动计算并积累梯度。 .backward()
方法触发反向传播过程,计算所有依赖该张量的梯度。- 提供
autograd
模块管理整个梯度计算流程。
下面将详细介绍自动微分的工作原理以及如何在代码中使用它。
2.1、自动微分的工作原理
在PyTorch中,自动微分通过构建计算图(computational graph)来实现。当我们创建一个需要求导的张量(Tensor)时,可以通过将其requires_grad
属性设置为True
来告诉PyTorch需要对该张量进行梯度计算。随后,对该张量进行的任何操作都会被记录到计算图中。
当我们完成前向传播(forward pass)的计算后,可以通过调用backward()
方法来启动反向传播(backward pass)。在反向传播过程中,PyTorch会根据计算图中的记录,从输出张量开始,逐层计算各个张量的梯度,并最终得到模型参数的梯度。
下面是一个简单的示例,演示了如何使用自动微分来计算一个线性回归模型的梯度:
import torch# 定义模型参数
w = torch.tensor([1.0], requires_grad=True)
b = torch.tensor([2.0], requires_grad=True)# 定义输入数据和标签
x = torch.tensor([3.0])
y = torch.tensor([4.0])# 前向传播
y_pred = w * x + b# 计算损失
loss = (y_pred - y) ** 2# 反向传播,计算梯度
loss.backward()# 查看参数梯度
print(w.grad) # 输出: tensor([2.])
print(b.grad) # 输出: tensor([-2.])
在这个例子中,我们首先定义了模型参数w
和b
,并将它们的requires_grad
属性设置为True
。然后,我们定义了输入数据x
和标签y
。在前向传播中,我们使用参数和输入数据计算预测值y_pred
。接下来,我们计算了预测值和真实值之间的损失。最后,我们调用loss.backward()
方法启动反向传播,计算参数的梯度。
2.2、停止梯度追踪
在有些情况下,我们可能不希望对某个张量进行梯度计算。这时,可以通过调用detach()
方法来停止对该张量的梯度追踪。例如:
x = torch.tensor([1.0], requires_grad=True)
y = x * 2
z = y.detach() * 3 # 停止对y的梯度追踪z.backward()print(x.grad) # 输出: None
在这个例子中,我们首先定义了一个需要求导的张量x
。然后,我们计算了y = x * 2
。接下来,我们通过调用detach()
方法停止了对y
的梯度追踪,并计算了z = y * 3
。最后,我们调用z.backward()
方法进行反向传播,但由于我们已经停止了对y
的梯度追踪,所以x
的梯度为None
。
2.3、禁用梯度计算
在模型评估阶段,我们通常不需要计算梯度。为了提高计算效率,可以通过使用torch.no_grad()
上下文管理器来禁用梯度计算。例如:
model = torch.nn.Linear(1, 1)# 训练模式,启用梯度计算
model.train()
with torch.enable_grad():x = torch.tensor([1.0], requires_grad=True)y_pred = model(x)loss = (y_pred - torch.tensor([2.0])) ** 2loss.backward()# 评估模式,禁用梯度计算
model.eval()
with torch.no_grad():x = torch.tensor([1.0])y_pred = model(x)loss = (y_pred - torch.tensor([2.0])) ** 2
在这个例子中,我们首先将模型设置为训练模式,并使用torch.enable_grad()
上下文管理器启用梯度计算。然后,我们进行了前向传播和反向传播的计算。接下来,我们将模型设置为评估模式,并使用torch.no_grad()
上下文管理器禁用梯度计算。在评估模式下,我们仍然可以进行前向传播的计算,但反向传播将被禁用,从而提高计算效率。
3、神经网络模块(nn.Module)
nn.Module
是构建深度学习模型的基本单元,允许用户以模块化的方式组织网络结构。- 用户通过继承
nn.Module
并实现forward
方法定义网络前向传播逻辑。 - 网络层、激活函数等都被封装为nn.Module的子类,方便复用和组合。
- 自动管理内部参数,包括权重和偏置,并支持模型保存和加载、设备迁移等功能。
下面将详细介绍如何使用nn.Module
来定义和使用神经网络:
3.1、定义神经网络
要使用nn.Module
定义神经网络,需要继承nn.Module
类并实现两个关键方法:__init__
和forward
。
3.1.1、 __init__
方法
在__init__
方法中,通常需要调用父类的构造函数,并定义网络中的各个层。例如,下面是一个简单的全连接神经网络的定义:
import torch.nn as nnclass MyNetwork(nn.Module):def __init__(self):super(MyNetwork, self).__init__()self.fc1 = nn.Linear(784, 128) # 定义第一个全连接层,输入为784,输出为128self.fc2 = nn.Linear(128, 64) # 定义第二个全连接层,输入为128,输出为64self.fc3 = nn.Linear(64, 10) # 定义第三个全连接层,输入为64,输出为10def forward(self, x):# 在forward方法中定义网络的前向传播过程x = self.fc1(x)x = nn.ReLU()(x) # 使用ReLU激活函数x = self.fc2(x)x = nn.ReLU()(x) # 使用ReLU激活函数x = self.fc3(x)return x
在这个例子中,我们定义了一个包含三个全连接层的神经网络。在__init__
方法中,我们使用nn.Linear
类定义了三个全连接层,并使用nn.ReLU
类定义了两个ReLU激活函数。
3.1.2、forward
方法
forward
方法是网络的前向传播过程,它接收输入数据并返回网络的输出。在上面的例子中,我们在forward
方法中定义了网络的计算流程,包括对输入数据进行全连接和激活函数的计算。
3.2、使用神经网络
一旦定义了神经网络,就可以使用它来进行训练和预测。下面是一个使用上面定义的神经网络进行训练的示例:
import torch# 创建网络实例
model = MyNetwork()# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# 加载数据集
# ...# 训练循环
for epoch in range(num_epochs):for inputs, labels in dataloader:# 前向传播outputs = model(inputs)loss = criterion(outputs, labels)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()
在这个例子中,我们首先创建了网络实例,然后定义了损失函数和优化器。接下来,我们使用数据加载器(dataloader
)加载数据集,并进行训练循环。在训练循环中,我们对每个批次的数据进行前向传播,计算损失,然后进行反向传播和优化。
通过继承nn.Module
类并实现__init__
和forward
方法,可以方便地定义和使用神经网络。nn.Module
提供了一种模块化的方式来组织网络的各个组件,并提供了丰富的层、损失函数和优化器等工具,使得构建神经网络变得更加简单和灵活。
4、优化器(Optimizer)
- 用于更新模型参数以最小化损失函数的工具,支持多种优化算法如SGD、Adam等。
- 参数更新基于反向传播得到的梯度,学习率等超参数对训练效果至关重要。
- 优化器可以根据不同的任务需求进行定制,同时可以配合正则化技术减少过拟合现象。
PyTorch提供了多种优化器,如SGD(随机梯度下降)、Adam(自适应矩估计)等。
4.1、优化器的使用
在PyTorch中,使用优化器通常包括以下几个步骤:
-
创建优化器实例:使用
torch.optim
模块中的优化器类来创建优化器实例。在创建时,需要指定模型的可学习参数(即需要更新的参数)以及其他超参数,如学习率、动量等。 -
清零梯度:在每次更新参数之前,需要清零上一次迭代中累积的梯度。可以使用优化器的
zero_grad()
方法来完成。 -
反向传播:通过调用损失函数的
backward()
方法来计算参数的梯度。这将根据自动微分机制,计算每个参数相对于损失函数的梯度。 -
更新参数:调用优化器的
step()
方法来更新模型的参数。优化器将根据计算得到的梯度和指定的优化算法来更新参数。
下面是一个使用Adam优化器的示例代码:
import torch
import torch.nn as nn
import torch.optim as optim# 定义模型
model = nn.Linear(10, 1)# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练循环
for epoch in range(10):for inputs, targets in dataloader:# 前向传播outputs = model(inputs)loss = criterion(outputs, targets)# 清零梯度optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()
4.2、参数组(param_groups)
优化器可以通过参数组(param_groups
)来对不同的参数应用不同的超参数。参数组是一个包含字典的列表,每个字典对应一组参数及其对应的超参数。在创建优化器时,可以通过传入一个包含参数组的列表来指定不同的超参数。
下面是一个示例代码,展示了如何为不同的参数组设置不同的学习率:
import torch
import torch.nn as nn
import torch.optim as optim# 定义模型
model = nn.Sequential(nn.Linear(10, 5),nn.ReLU(),nn.Linear(5, 1)
)# 定义参数组
param_groups = [{'params': model[0].parameters()}, # 第一个全连接层的参数{'params': model[2].parameters(), 'lr': 0.0001} # 第二个全连接层的参数,学习率为0.0001
]# 创建优化器,并指定参数组
optimizer = optim.Adam(param_groups)
4.3、学习率调整
在训练过程中,学习率的调整对于模型的收敛和泛化能力至关重要。PyTorch提供了一些方法来动态调整学习率,如学习率调度器(lr_scheduler
)。学习率调度器可以根据预设的策略(如固定间隔调整、指数衰减等)来调整优化器的学习率。
下面是一个使用学习率调度器的示例代码:
import torch
import torch.nn as nn
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler# 定义模型、损失函数和优化器
model = nn.Linear(10, 1)
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 创建学习率调度器,每10个epoch将学习率减半
scheduler = lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)# 训练循环
for epoch in range(100):for inputs, targets in dataloader:# 前向传播、反向传播和更新参数outputs = model(inputs)loss = criterion(outputs, targets)optimizer.zero_grad()loss.backward()optimizer.step()# 更新学习率scheduler.step()
通过合理选择和使用优化器,可以提高模型的训练效率和性能。
5、数据加载器(DataLoader)
在PyTorch中,数据加载器(DataLoader)是用于高效加载和管理数据的重要工具。
- 数据加载器基于
torch.utils.data.Dataset
接口,实现了数据批处理、混洗、并行加载等功能。 - 通过设置批处理大小来平衡计算效率和内存消耗,同时保证模型训练过程的随机性。
- 可以无缝衔接训练过程,使得数据准备、训练和验证更加高效便捷。
5.1、Dataset类
在使用DataLoader之前,需要先定义一个继承自torch.utils.data.Dataset
的类,用于描述数据集的结构和加载方式。这个类需要实现两个方法:
__len__(self)
:返回数据集中样本的数量。__getitem__(self, index)
:根据索引返回对应的样本数据和标签。
下面是一个简单的示例,定义了一个包含图像和标签的数据集:
from torch.utils.data import Datasetclass ImageDataset(Dataset):def __init__(self, image_paths, labels):self.image_paths = image_pathsself.labels = labelsdef __len__(self):return len(self.image_paths)def __getitem__(self, index):image_path = self.image_paths[index]label = self.labels[index]# 在这里进行图像的加载和预处理image = load_and_preprocess_image(image_path)return image, label
5.2、DataLoader类
在定义了Dataset类之后,就可以使用DataLoader来加载和管理数据集。DataLoader提供了一些常用的参数来控制数据的加载方式:
dataset
:要加载的数据集,即之前定义的Dataset类的实例。batch_size
:每个批次中样本的数量。shuffle
:是否在每个迭代周期中打乱数据的顺序,默认为False。num_workers
:用于数据加载的子进程数量,默认为0,表示在主进程中进行数据加载。pin_memory
:是否将数据复制到CUDA固定内存中,以加快数据传输速度,默认为False。
下面是一个使用DataLoader加载之前定义的ImageDataset的示例:
from torch.utils.data import DataLoaderdataset = ImageDataset(image_paths, labels)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=4)
5.3、使用DataLoader进行数据迭代
在训练和评估过程中,可以使用迭代器来从DataLoader中获取数据。下面是一个在训练过程中使用DataLoader的示例:
for epoch in range(num_epochs):for images, labels in dataloader:# 在这里进行模型的前向传播、反向传播和参数更新pass
在每个迭代周期中,DataLoader会按照指定的批大小从数据集中加载数据,并返回一个包含数据和标签的元组。可以使用这些数据来进行模型的训练或评估。
通过使用PyTorch的DataLoader,可以方便地加载和管理数据集,并进行高效的数据迭代。在使用时,需要先定义一个Dataset类来描述数据集的结构和加载方式,然后使用DataLoader来加载和管理数据集,并使用迭代器来进行数据的获取和处理。
6、损失函数(Loss Function)
- 用于衡量模型预测结果与真实目标之间差异的数学函数,目标是通过优化过程最小化损失。
- 根据任务类型选择不同的损失函数,如MSE用于回归任务,交叉熵损失用于分类任务等。
- 结合正则化项可以约束模型复杂度,提高泛化能力,并且在多目标问题中可能需要组合多个损失函数。
在机器学习中,损失函数(Loss Function)用于衡量模型的预测结果与真实标签之间的差异。在PyTorch中,损失函数是训练模型的关键组成部分,它们可以帮助优化器确定如何调整模型参数以最小化预测误差。
6.1、损失函数的类型
PyTorch提供了多种损失函数,适用于不同的任务和数据类型。一些常见的损失函数包括:
- 均方误差损失(Mean Squared Error,MSE):用于回归任务,计算预测值和真实值之间的均方误差。
- 平均绝对误差损失(Mean Absolute Error,MAE):用于回归任务,计算预测值和真实值之间的平均绝对误差。
- 交叉熵损失(Cross Entropy Loss):用于分类任务,尤其是多分类问题,计算预测概率分布和真实标签之间的交叉熵。
- 二分类交叉熵损失(Binary Cross Entropy Loss):用于二分类任务,计算预测概率和真实标签之间的交叉熵。
- Dice损失(Dice Loss):用于图像分割任务,基于Dice系数计算预测和真实标签之间的相似性。
6.2、使用损失函数
在PyTorch中,可以使用torch.nn
模块中的损失函数类来计算损失。下面是一个使用交叉熵损失函数的示例:
import torch
import torch.nn as nn# 定义模型
model = nn.Linear(10, 3) # 假设输入特征维度为10,分类类别数为3# 定义损失函数
criterion = nn.CrossEntropyLoss()# 定义优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# 输入数据和标签
input_data = torch.randn(64, 10) # 64个样本,每个样本有10个特征
target = torch.randint(0, 3, (64,)) # 64个样本的标签,取值范围为[0, 3)# 前向传播
output = model(input_data)# 计算损失
loss = criterion(output, target)# 反向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
在这个示例中,我们定义了一个线性回归模型,用于进行多分类任务。我们使用交叉熵损失函数来计算模型的预测结果与真实标签之间的差异。在每个训练步骤中,我们首先进行前向传播,然后计算损失,接着进行反向传播和参数更新。
6.3、自定义损失函数
除了使用PyTorch提供的损失函数外,还可以根据需要自定义损失函数。自定义损失函数需要继承自nn.Module
类,并实现forward
方法来计算损失。下面是一个自定义Dice损失函数的示例:
import torch
import torch.nn as nn
import torch.nn.functional as Fclass DiceLoss(nn.Module):def __init__(self):super(DiceLoss, self).__init__()def forward(self, input, target):smooth = 1.0iflat = input.view(-1)tflat = target.view(-1)intersection = (iflat * tflat).sum()return 1 - ((2.0 * intersection + smooth) / (iflat.sum() + tflat.sum() + smooth))# 使用自定义的Dice损失函数
dice_loss = DiceLoss()
loss = dice_loss(output, target)
在这个示例中,定义了一个Dice损失函数,用于图像分割任务。在forward
方法中,我们计算了预测结果和真实标签之间的Dice系数,并返回1减去Dice系数作为损失值。
损失函数是PyTorch中用于衡量模型预测误差的重要工具。根据任务和数据类型的不同,可以选择合适的损失函数来指导模型的训练。同时,也可以根据需要自定义损失函数,以满足特定的任务需求。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏、分享下吧,非常感谢!👍 👍 👍
🔥🔥🔥道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
💖The End💖点点关注,收藏不迷路💖 |