7.3基础概念/文件、文件路径/batch_size,length,total/acc、loss计算/ect

一、

一些基础术语:
util是utility的缩写,意思为实用工具。一般用于描述和业务逻辑没有关系的数据处理分析工具。
logger :日志
meter : 记录表
使用下划线 _ 表示不需要的变量是一种常见的开发者的约定,(Python 解释器本身对下划线并没有特殊处理,它不会自动忽略赋值给下划线的值或在未使用的情况下跳过它。下划线只是一个普通的变量名,与其他变量名没有区别。)

二、

N = len(trainloader.dataset),其中trainloader.dataset表示数据加载器所加载的数据集对象。这将返回训练数据集中的样本数量。
每次从trainloader中获取的是一个批次(batch)的数据B = len(trainloader)返回的是trainloader中批次的数量,也就是数据集被分成了多少个批次。这个值可以用于迭代训练数据集,或者用于确定训练的总步数或迭代次数。
将N(全部数据集)分成B个batch,每次update(compute gradient & optimizer.step() )是update一个batch的参数量,所以这也就说明了为什么每个batch里面要先进行optimizer.zero_grad()
而一个epoch是指把全部的数据集过了一遍,称为一个epoch

三、

训练集、验证集、测试集的关系:
abbrtrain、val、test
(1) 训练集相当于课后的练习题,用于日常的知识巩固。
(2) 验证集相当于周考,用来纠正和强化学到的知识。
(3) 测试集相当于期末考试,用来最终评估学习效果。
大部分时候,没有验证集,为了让测试集有更好的表现,不从训练集中抽取20%作为验证集。
在这里插入图片描述

四、

model.eval()with torch.no_grad()的配合:
model.eval() 是一种模型状态转换操作,用于将模型切换到评估模式。在评估模式下,模型的行为可能会有所不同,例如,对于某些层(如 Dropout)来说,它们可能会被禁用或修改。评估模式下的模型通常更接近实际应用场景,并用于计算测试集上的指标。
with torch.no_grad() 是一个上下文管理器,用于在代码块中临时关闭梯度计算。在这个代码块内部,所有的操作都不会被跟踪,也不会计算梯度。这对于在测试阶段或者不需要进行反向传播的代码段非常有用,可以提高代码的执行效率。
with torch.no_grad() 控制梯度计算,model.eval() 控制模型的行为模式,二者常常一起使用以确保测试阶段的有效评估。

五、

文件读写f.close() & f.flush()

  • f.close() 关闭文件对象,执行一系列清理操作,使文件对象不再可用。一旦文件被关闭,无法再对其进行读取或写入操作。
  • f.flush() 刷新文件缓冲区,确保缓冲区中的数据被写入文件。文件对象仍然保持打开状态,可以继续对其进行读取或写入操作。

为了保险起见,建议在关闭文件对象之前手动调用 f.flush() 来刷新缓冲区,确保所有未写入的数据都被写入文件
通常情况下,在处理完文件操作后,应该调用 f.close() 来关闭文件,释放相关资源。而 f.flush() 则常用于在文件操作过程中手动刷新缓冲区,确保数据写入文件,特别是在需要保证数据实时写入的场景下。
虽然最后Python 解释器会在程序执行结束时自动关闭所有打开的文件对象。这是因为在程序退出时,Python 会清理和释放所有资源,包括打开的文件对象。但为了代码的可维护性和文件的完整性,建议在不再使用文件对象时显式地调用 f.close() 关闭文件。
或者,你也可以使用 with 语句来自动管理文件对象的关闭,它会在代码块执行完毕后自动关闭文件对象

with open('file.txt', 'r') as f:
    # 进行文件读取操作
    # 不需要手动关闭文件对象

六、文件& 文件路径操作

1、
如果想创建子目录,必须用参数-p,不然就会认为你的当前要创建的文件夹名字中有/
mkdir -p dir1/dir2/dir3
这将递归地创建 dir1、dir2 和 dir3 目录,无论它们是否已存在。

2、

if not os.path.exists(path) # 对于路径中的 /,它会被视为普通的字符,而不是路径的分隔符
	os.makedirs()
if not os.path.isdir(path) # 用这一套,会把 / 视为路径逐级创建文件夹
	os.makedirs()

使用 os.path.isdir() 函数来逐级检查路径中的目录。这样可以确保路径中的每个目录都存在,而不仅仅是最后一个目录或文件
os.makedirs 中,斜杠 / 不会被解释为文件夹名字的一部分。它只是用来表示目录结构的层次关系。

3、
下面两个的区别:

a = os.path.join(a, b) # 调用函数
a = a + b # 字符串拼接

二者效果一样,但推荐使用os.path.join因为它可以正确处理路径分隔符,以适应不同的操作系统。即,你不需要在乎是用\还是/,会根据你操作系统自动给你创建,

4、
“w”:会覆盖之前的文件
“a”:追加
二者在文件不存在的时候都会自动创建文件

with open(file_path, 'a') as file:
    if file.tell() != 0:
        file.write('\n')  # 写入空行
    file.write(data)  # 追加数据

file.tell() 方法用于获取当前文件指针的位置。如果文件指针位置为 0,表示文件为空

七、

几个参数:

  1. batch_size 你自己设置的一个batch的数量
  2. labels.size(0)等价于len(labels),它表示理想情况下一个批次中的样本数量。一个批次中的样本数量不一定等于batch_size,因为可能有整除不了的情况。
  3. total += labels.size(0) 这样获得的是精确的样本的数量
  4. len(trainloader)是一共有多少个batch
    第35 / 200(epoch)轮:选的batch_size=64,所以一个dataset划分为642(len(trainloader))个小的batch
    一个epoch下来要把整个dataset跑一遍,不过最小单位是batch
    在这里插入图片描述
total += labels.size(0)

用于累积所有批次中的样本数量。通过每个批次的样本数量相加,可以得到总样本数量。

八、

1、准确率计算

outputs = model(inputs)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += predicted.eq(labels.data).cpu().sum()
# correct += (predicted == labels).sum()

outputs 是模型的输出,通常是一个张量,其形状为 [batch_size, num_classes],其中 batch_size 是当前批次的大小,num_classes 是分类的类别数。
torch.max(outputs.data, 1) 是一个函数调用,它对 outputs.data 张量沿着指定的维度进行最大值的计算第二个参数 1 表示沿着第二个维度(即列维度,即num_classes!)进行计算
返回:
第一个张量是最大值的张量,不需要使用,用 ‘_’ 忽略
第二个张量是最大值的索引张量,表示每个样本在输出类别上的最大值的索引。它是一个形状为 [batch_size] 的张量(一维张量same as labels,一共有bs个样本,就有bs个最大值),其中每个元素表示相应样本的预测类别
total += labels.size(0)total 的作用是跟踪训练过程中已处理的样本总数,用于(实时args.print_freq)计算训练准确率,它是根据每个批次中处理的样本数进行累加的,因此它不等于数据集的总样本数量。
correct += predicted.eq(labels.data).cpu().sum() 将预测结果与真实标签进行逐元素比较,返回一个布尔张量(最简单的一维数组,size:(batch_size,) ),其中相等的位置为 True,不相等的位置为 False。(将布尔张量转移到 CPU 上,因为默认情况下模型和数据可能在 GPU 上。)sum()计算布尔张量中 True 的数量,也就是预测正确的样本数量(scalar标量)。
最后,将预测正确的样本数量累加到 correct 中,以便在训练过程中跟踪正确的样本数量。
2、loss计算

loss = criterion(outputs, labels)
loss.backward()
sum_loss += loss.item()

平均损失的计算是基于每个批次的损失值

def train_one_epoch(args,model,epoch,trainloader,optimizer,criterion,f2):
    print('\nEpoch: %d' % (epoch + 1))
    model.train()
    sum_loss = 0.0
    correct = 0.0
    total = 0.0
    for i, (inputs, labels) in enumerate(tqdm(trainloader), 0): 
        # 1.准备数据
        length = len(trainloader)
        if args.cuda == True:
            inputs, labels = inputs.cuda(), labels.cuda()
        # 2.前向传播+计算损失
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        # 3.清零梯度反向传播更新参数
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        sum_loss += loss.item()

        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += predicted.eq(labels.data).cpu().sum()
        
        if i % args.print_freq == 0:
            f2.write('Epoch:[%03d][%03d/%03d] |Loss: %.03f | Acc: %.3f%%\n'
                    % (epoch + 1, i, length, sum_loss / (i + 1), 100. * correct / total))
        f2.flush()

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值