上一次的笔记学习到了pytorch的张量操作,接下来将从自动微分以及torch.nn模块还有数据预处理这三个方面入手,进行分享。
一、pytorch自动微分
1.什么是自动微分?
自动微分用于计算神经网络中参数的梯度,以便进行优化。自动微分一般是用反向传播算法,它会沿着神经网络图反向路径传播梯度,自动推导出损失函数对于每个参数的导数,找到损失值最小的参数取值。这种方法使得深度学习模型的开发和调试过程大大地得到了简化。
2.代码实现
torch中包含了torch.autograd模块,这可以帮助我们实现任意标量值自动求导的类和函数
具体操作就是:设置“requires_grad=True”
这里我给出代码举例:
说实话我不是很懂这个标量值54是怎么算出来的
在我再三逼问gpt之后得到了以下回答:
也就是说,自动微分是对张量里的每一个元素通过你所给出的函数,处理后把每一个数加起来,当然这个操作的前提是有一个式子,如果只是对张量进行微分的话貌似得到的是(x.)。
二、torch.nn模块
本处仅对torch.nn进行简单的介绍,具体的操作将在后续的笔记中呈现。
1.什么是torch.nn?
nn就是neural network的缩写,主要用于构建神经网络模型比如前馈神经网络、卷积神经网络、循环神经网络等,适用于图像分类、目标检测、语义分割、文本分类、语言模型等等。
2.它有哪些组件?
各类层、激活函数、损失函数、优化器
首先是层(layer)。层是网络的构建块,用于从输入数据中提取特征并执行各种转换。常用的层有:
(1)全连接层(nn.Linear):将输入与每个神经元相连接,用于学习输入数据中的线性关系。
(2)卷积层(nn.Conv2d):通过卷积核在输入数据上滑动,从而提取输入数据中的空间特征。(图像处理)
(3)池化层(nn.MaxPool2d):对输入数据的子区域进行池化操作,以减少数据量并保留最重要的特征。
(4)循环神经网络层(nn.RNN):用于处理序列数据,通过循环单元在时间步之间传递信息。
然后是激活函数(Activation Funtions)。激活函数是在神经网络中引入非线性的关键组件,它们将神经元的输入映射到输出。常用的激活函数有:
(1)ReLU(Rectified Linear Unit):f(x) = max(0, x),在深度学习中广泛使用,能够有效地缓解梯度消失问题。
(2)Sigmoid:f(x) = 1 / (1 + exp(-x)),用于二分类问题,在输出范围为 (0, 1) 之间。
(3)Tanh(双曲正切):f(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x)),也是一种常用的激活函数,输出范围在 (-1, 1) 之间。
还有损失函数。损失函数(Loss Function)是用来衡量模型预测值与真实标签之间的差异或误差的函数。在训练神经网络时,优化算法的目标是最小化损失函数,使模型能够更准确地预测目标变量。常用的损失函数有:
(1)均方误差损失函数(Mean Squared Error Loss):nn.MSELoss:用于回归任务,衡量模型输出与真实标签之间的平均平方差。
(2)交叉熵损失函数(Cross-Entropy Loss):nn.CrossEntropyLoss用于多分类任务,特别适用于二分类任务。
(3)负对数似然损失函数(Negative Log Likelihood Loss):nn.NLLLoss用于多分类任务,通常与对数Softmax函数结合使用。公式类似于交叉熵损失函数,但在输入之前不会应用 Softmax 激活函数。
最后是优化器(Optimizers)。优化器用于调整神经网络的权重和偏置,以最小化损失函数。它们通过计算损失函数关于权重和偏置的梯度,并根据梯度更新网络参数。常见的优化器包括:
(1)随机梯度下降(Stochastic Gradient Descent,SGD):torch.optim.SGD是最基本的优化算法之一,通过计算损失函数对每个参数的梯度,并沿着梯度的反方向更新参数。
(2)Adam:torch.optim.Adam结合了动量方法和自适应学习率方法的优化算法,通常在深度学习中表现很好。它使用指数衰减的移动平均来估计每个参数的梯度和二阶矩,并根据这些估计来更新参数。
(3)Adagrad:torch.optim.Adagrad自适应学习率方法之一,对每个参数应用不同的学习率,根据梯度的历史信息来进行自适应调整。适用于稀疏数据或梯度幅度差异较大的情况。
(4)RMSprop:torch.optim.RMSprop也是一种自适应学习率方法,类似于 Adagrad,但使用指数衰减的平均来估计梯度的二阶矩。通过使用指数衰减平均,RMSprop 可以更好地适应不同参数的梯度变化。公式类似于 Adagrad,但使用指数衰减的梯度二阶矩替代了梯度累积平方和。
三、Pytorch中数据操作和预处理
Pytorch中进行数据预处理的模块是torch.utils.data,它的常用函数类包括以下几个:
类 | 功能 |
---|---|
torch.utils.data.TensorDataset() | 将数据处理为张量 |
torch.utils.data.ConcatDataset() | 连接多个数据集 |
torch.utils.data.subset() | 根据索引获取数据集的子集 |
torch.utils.data.DataLoader() | 数据加载器 |
torch.utils.data.random_split() | 随即将数据集拆分为给定长度的非重叠新数据集 |
1. torch.data.TensorDataset()
TensorDataset 的作用是将多个张量作为输入,并将它们打包成一个数据集,其中每个张量的第一个维度被视为样本维度。在训练神经网络时,通常将输入数据张量(如特征)和目标数据张量(如标签)打包成 TensorDataset。
下面我将给出一个简单的例子,作为使用的模板:
import torch
from torch.utils.data import TensorDataset
# 假设有两个张量作为输入数据和目标数据
input_data = torch.randn(100, 5) # 假设有 100 个样本,每个样本有 5 个特征
target_data = torch.randint(0, 2, (100,)) # 假设有 100 个样本的二分类标签(0 或 1)
# 使用 TensorDataset 封装输入数据和目标数据
dataset = TensorDataset(input_data, target_data)
# 可以像使用其他数据集一样访问数据集中的元素
for i in range(len(dataset)):
sample, target = dataset[i]
print(f"Sample {i}: {sample}, Target: {target}")
在这个例子中,input_data 和 target_data 分别代表输入数据张量和目标数据张量。我们将它们作为参数传递给 TensorDataset 构造函数,从而创建了一个数据集对象 dataset。然后,我们可以通过索引 dataset 来访问其中的样本数据和对应的目标数据。
下图是实战——将数据集处理为张量的封装操作,思路是:
使用torch.utils.TensorDataset()来封装数据
通过索引来访问数据
然后使用len函数来显示数据集大小
2.torch.utils.DataLoader
torch.utils.data.DataLoader 是 PyTorch 中用于批量加载数据的实用工具类,通常与 Dataset 对象一起使用。它提供了对数据的批处理、随机打乱和并行加载等功能,可以有效地提高模型训练的效率和性能。主要作用是将数据集对象(如 TensorDataset)封装为一个可迭代的数据加载器,从而可以在训练过程中按批次加载数据。这样可以使得模型在训练时每次都能够从数据集中加载一个批次的数据进行训练,而不是一次性加载整个数据集。这对于处理大规模数据集时尤其有用,可以节省内存并加快训练速度。
接下来我将给出DataLoader的使用模板
import torch
from torch.utils.data import TensorDataset, DataLoader
# 假设有一个数据集对象 dataset(例如,由 TensorDataset 创建)
input_data = torch.randn(100, 5) # 假设有 100 个样本,每个样本有 5 个特征
target_data = torch.randint(0, 2, (100,)) # 假设有 100 个样本的二分类标签(0 或 1)
dataset = TensorDataset(input_data, target_data)
# 使用 DataLoader 将数据集对象封装成一个数据加载器
batch_size = 32 # mini batch size
shuffle = True # 是否打乱数据集顺序
num_workers = 4 # 加载数据的子进程数,多线程读取数据(通常设置为 CPU 核心数)
data_loader = DataLoader(dataset, batch_size=batch_size, shuffle=shuffle, num_workers=num_workers)
# 可以像使用迭代器一样遍历数据加载器,每次迭代得到一个批次的数据
for batch in data_loader:
inputs, targets = batch
# 接下来就是对批次数据进行模型训练或其他操作
参考书上的例子,对CSV文件使用了这两种方法来进行读取数据与预处理:
数据集 spambase.csv 用的是 UCI 机器学习存储库里的垃圾邮件数据集,它一条数据有57个特征和1个标签。
import torch.utils.data as Data
import pandas as pd # 这个包用来读取CSV数据
import torch
# 继承Dataset,定义自己的数据集类 mydataset
class mydataset(Data.Dataset):
def __init__(self, csv_file): # self 参数必须,其他参数及其形式随程序需要而不同,比如(self,*inputs)
data_csv = pd.DataFrame(pd.read_csv(csv_file)) # 读数据
self.csv_data = data_csv.drop(axis=1, columns='58', inplace=False) # 删除最后一列标签
def __len__(self):
return len(self.csv_data)
def __getitem__(self, idx):
data = self.csv_data.values[idx]
return data
data = mydataset('spambase.csv')
x = torch.tensor(data[:5]) # 前五个数据
y = torch.tensor([1, 1, 1, 1, 1]) # 标签
torch_dataset = Data.TensorDataset(x, y) # 对给定的 tensor 数据,将他们包装成 dataset
loader = Data.DataLoader(
# 从数据库中每次抽出batch size个样本
dataset = torch_dataset, # torch TensorDataset format
batch_size = 2, # mini batch size
shuffle=True, # 要不要打乱数据 (打乱比较好)
num_workers=2, # 多线程来读数据
)
def show_batch():
for step, (batch_x, batch_y) in enumerate(loader):
print("steop:{}, batch_x:{}, batch_y:{}".format(step, batch_x, batch_y))
show_batch()
鉴于书上内容在此部分讲述的内容较少,故“另辟蹊径”在CSDN上查找了其他博主的例子。本次的读书笔记主要是介绍了自动微分是什么,以及它如何进行自动微分的详细步骤;概括地介绍了torch.nn模块的内容以及数据预处理的内容,并且对torch.utils.data.TensorDataset() 和torch.utils.data.DataLoader()进行了代码介绍以及实战使用的例子。
参考资料:
[1]:Pytorch构建数据集——torch.utils.data.Dataset()和torch.utils.data.DataLoader()
https://blog.csdn.net/weixin_41560402/article/details/108121344
[2]:《Pytorch深度学习入门与实战》孙玉林、余本国