系列文章目录
PyTorch张量(Tensor)对象的一些常见方法和函数的使用,以及损失的计算方式。
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、.tolist()?
将PyTorch张量转换为Python列表,该列表包含了与原始张量相同的数据内容
该方法非常有用,这样可以使数据更易于处理和使用,例如进行可视化、计算统计量、保存到文件等操作。
import torch
# 创建一个PyTorch张量
tensor = torch.tensor([1, 2, 3, 4, 5])
# 将张量转换为Python列表
tensor_list = tensor.tolist()
print(tensor_list)
# [1, 2, 3, 4, 5]
一、squeeze()和unsqueeze()函数的用法?
.unsqueeze(1)将一维的标签张量转换为二维的标签张量,以便与其他张量进行运算或匹配。新插入的维度可以理解为扩展了样本维度。
而squeeze()
函数的作用是去除张量中维度大小为1的维度,从而降低张量的维度。
import torch
labels = torch.tensor([1, 2, 3, 4]) # 一维张量,形状为(4,)
expanded_labels = labels.unsqueeze(1) # 在第一个维度之后插入新的维度
print(expanded_labels.shape) # 输出: (4, 1)
print(expanded_labels)
# tensor([[1],
[2],
[3],
[4]])
二、detach()函数
1. 计算损失时
初始化 mean_loss 为零张量,使用了加权平均的方法,将当前步骤的损失
loss
与之前的平均损失mean_loss
进行加权平均计算。在以下示例中detach()
函数用于将计算图截断,将loss
的梯度计算与计算图分离,以确保在更新mean_loss
时不会影响梯度的计算。
mean_loss = torch.zeros(1).to(device) for step, data in enumerate(data_loader): images, labels = data # 模型前向传播 pred = model(images.to(device)) loss = loss_function(pred, labels.to(device)) loss.backward() mean_loss = (mean_loss * step + loss.detach()) / (step + 1)
print(torch.zeros(1))的结果将打印一个张量对象,其值为0:tensor([0.])。可以进行各种张量操作,如加法、乘法等。
mean_loss
需要参与到 PyTorch 的张量计算中,如进行反向传播、梯度更新等。不同于普通的标量变量。技术其初始值为零张量,但在实际的训练过程中,
mean_loss
通常会根据损失函数和梯度进行更新。
2.理解代码中的损失计算方式
由于训练数据集可能非常大,无法一次性加载到内存中进行训练,因此使用批处理的方式进行训练。每个批次的样本被用于模型的前向传播和损失计算,并且梯度是根据这个批次的损失进行计算和更新的。
batch_size = 32
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=nw)
train_steps = len(train_loader)train_steps的结果将是将训练数据集的总样本数除以批次大小(batch_size)得到的结果向上取整。
这是因为在每个训练步骤中,数据加载器会生成一个批次的样本供模型进行训练。
train_steps的结果表示了一个 epoch 中的训练步数,即模型将通过多少个批次的样本进行训练。
一个 epoch 的总损失是所有批次的损失之和。
如果将总损失除以train_steps,就相当于将总损失平均分配给每个训练步骤,得到了每个训练步骤的平均损失。通过计算平均损失,可以减少批次大小和训练数据集大小对损失值的影响,使得不同批次、不同数据集大小之间的损失可比性更强。这有助于更好地理解和比较模型的训练效果。
以下代码中关于计算的是“什么”损失?立即答:每个批次的平均损失。常见的做法:
train_steps = len(train_loader)
for epoch in range(epochs):
# train
net.train()
running_loss = 0.0
train_bar = tqdm(train_loader, file=sys.stdout)
for step, data in enumerate(train_bar):
images, labels = data
optimizer.zero_grad()
outputs = net(images.to(device))
loss = loss_function(outputs, labels.to(device))
loss.backward()
optimizer.step()
# print statistics
running_loss += loss.item()
print('[epoch %d] train_loss: %.3f ' %
(epoch + 1, running_loss / train_steps))
running_loss是全部数据的累计损失,但在打印 train_loss时,它被除以 train_steps,表示的是每个批次的平均损失。这样做的目的是为了更好地评估每个批次的训练效果,尽量消除批次大小对损失值的影响,使得不同批次之间的损失可比性更强。
2.len()函数
返回一个对象的长度或元素的个数
对于数据加载器(
train_loader
)(数据加载器会自动将数据集按照指定的批次大小划分为多个批次,并在每个训练步骤中提供一个批次供模型使用),len()返回的是加载器中的批次数量,而不是每个批次中的样本数量,即数据集中样本的总数除以批次大小。
总结
以上就是今天要讲的内容,谢谢观看!