1、pip包安装

在子豪兄的视频里,他是在JupyterLab中输入这行代码进行的pip包安装。但是我发现特别的慢。所以我注释掉了,然后去终端安装的。

Image
这里显示□就多试几次,直到出现中文。

Image

2、迁移学习

Image

Image

Image

Image

然后是定义数据加载器这里,通过询问DeepSeek,我得到了相关的训练建议:
提问的Prompt:

rtx3060跑resnet50,30万张图片,你觉得参数都调多少合适? 这些都该怎么调?你一一帮我修改:"""定义数据加载器DataLoader
from torch.utils.data import DataLoader

BATCH_SIZE = 32

# 训练集的数据加载器
train_loader = DataLoader(train_dataset,
                          batch_size=BATCH_SIZE,
                          shuffle=True,
                          num_workers=4
                         )

# 测试集的数据加载器
test_loader = DataLoader(test_dataset,
                         batch_size=BATCH_SIZE,
                         shuffle=False,
                         num_workers=4
                        )
导入训练需使用的工具包
from torchvision import models
import torch.optim as optim
from torch.optim import lr_scheduler
选择迁移学习训练方式
斯坦福CS231N【迁移学习】中文精讲:https://www.bilibili.com/video/BV1K7411W7So

斯坦福CS231N【迁移学习】官方笔记:https://cs231n.github.io/transfer-learning

如果你的数据集和MS COCO数据集的图像域类似(街景、动植物、生活用品),可以保留预训练模型权重,在自己的数据集上迁移学习微调分类输出层或所有层。站在巨人的肩膀上,复用预训练模型在MS COCO数据集上学习到的图像特征。(Transfer Learning, Fine Tuning)

如果你的数据集和MS COCO数据集的图像域不类似(医疗影像、显微镜图像、工业检测、天文照片、动画、油画),可以随机初始化模型权重,在自己的数据集上重新训练所有层。(From Scratch)。或者冻结底层权重,只重新训练顶层,复用预训练模型在MS COCO数据集上学习到的底层图像特征。

选择一:只微调训练模型最后一层(全连接分类层)
model = models.resnet18(pretrained=True) # 载入预训练模型

# 修改全连接层,使得全连接层的输出与当前数据集类别数对应
# 新建的层默认 requires_grad=True
model.fc = nn.Linear(model.fc.in_features, n_class)
model.fc
Linear(in_features=512, out_features=30, bias=True)
# 只微调训练最后一层全连接层的参数,其它层冻结
optimizer = optim.Adam(model.fc.parameters())
选择二:微调训练所有层
# model = models.resnet18(pretrained=True) # 载入预训练模型

# model.fc = nn.Linear(model.fc.in_features, n_class)

# optimizer = optim.Adam(model.parameters())
选择三:随机初始化模型全部权重,从头训练所有层
# model = models.resnet18(pretrained=False) # 只载入模型结构,不载入预训练权重参数

# model.fc = nn.Linear(model.fc.in_features, n_class)

# optimizer = optim.Adam(model.parameters())
训练配置
model = model.to(device)

# 交叉熵损失函数
criterion = nn.CrossEntropyLoss() 

# 训练轮次 Epoch
EPOCHS = 30

# 学习率降低策略
lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.5)"""我使用的数据集特征如下:"""高内在歧义性(High Intrinsic Ambiguity):数据集中的植物图像在视觉上具有很高的相似性,即使是专家也很难仅凭肉眼进行准确识别,这增加了分类任务的难度。

长尾分布(Long-tailed Distribution):数据集中的类别呈现长尾分布,即少数物种的图像数量占据了大部分,而许多物种的图像数量很少,这导致了类别之间的不平衡。

大规模和多样性:Pl@ntNet-300K包含306,146张植物图像,涵盖了1,081个物种,这为评估集合值分类方法和算法提供了丰富的样本。

数据集构建方法:作者通过从Pl@ntNet数据库中随机选择部分属(genera),并保留这些属中的所有物种来构建数据集,这种方法保留了原始数据库中固有的歧义性。

评估指标:论文推荐了两种与数据集相关的集合值评估指标:宏观平均top-k准确率(macro-average top-k accuracy)和宏观平均average-k准确率(macro-average average-k accuracy),这些指标更适合评估集合值分类器的性能。

基线结果:作者提供了使用交叉熵损失训练的深度神经网络的基线结果,这为后续研究提供了一个起点。

实际应用背景:Pl@ntNet-300K数据集是从Pl@ntNet项目中收集的现实世界图像中提取的,该项目是一个大规模的公民科学观测项目,致力于通过基于图像的植物识别收集植物发生数据。

数据验证和清洗:论文描述了一种基于加权多数投票算法的标签验证方法,以及数据清洗流程,包括自动化过滤不适当或不相关内容以及基于用户评估的图像质量过滤。"""

思考:

嗯,用户现在在用RTX 3060跑ResNet50处理30万张图片,想知道怎么调整参数。他们的数据集是Pl@ntNet-300K,具有高歧义性、长尾分布等特点。我得先看看他们提供的代码,然后结合数据集特性来给出建议。

首先,数据加载部分。他们原来的batch size是32,num_workers是4。考虑到RTX 3060的显存可能不是特别大,但30万张图片的话,可能可以适当增大batch size以提高训练速度。不过ResNet50本身参数多,显存占用大,所以需要平衡。可能32到64之间比较合适。num_workers可以增加到8或者根据CPU核心数调整,如果CPU允许的话,这样数据加载更快,避免成为瓶颈。

然后是数据预处理部分。他们可能没有提到数据增强,但高歧义性的数据集需要更多的增强来提升模型泛化能力。比如随机裁剪、颜色抖动、旋转等。另外,长尾分布的问题,可能需要用加权采样或者类平衡采样器,比如在DataLoader里设置sampler参数,使用WeightedRandomSampler或者类似的方法来处理类别不平衡。

接下来是模型选择。用户提到是否微调。他们的数据集是植物图像,和ImageNet可能有一定的相似性,所以应该用预训练模型进行微调。但类别是长尾分布,可能需要调整全连接层,并考虑分层学习率,比如后面层的lr大一些,前面层小一些,或者用不同的优化器参数组。

优化器部分,他们原来用的是Adam,但可能SGD更适合微调,尤其是在预训练模型上。Adam虽然收敛快,但SGD加动量可能在最终准确率上更好,尤其是结合适当的学习率调整。学习率调度方面,StepLR可能不够灵活,可以考虑CosineAnnealingLR或者ReduceLROnPlateau,根据验证集表现调整。

损失函数方面,长尾分布的问题,CrossEntropyLoss可能不够,需要加上类别权重,或者用Focal Loss来处理难例和类别不平衡。比如在CrossEntropyLoss中设置weight参数,根据每个类别的样本数计算权重。

训练轮次EPOCHS设为30可能不够,特别是数据量大,可能需要更多轮次,比如50或更多,配合早停法防止过拟合。学习率调整策略也需要相应调整,比如每10个epoch降一次,或者根据验证损失来调整。

另外,评估指标方面,用户的数据集用了macro-average top-k和average-k指标,所以训练过程中需要实现这些指标的计算,而不仅仅是常规的准确率。可能需要自定义评估函数。

还有,显存限制的问题。RTX 3060的显存可能12GB,如果batch size太大可能不够。可以用梯度累积来模拟更大的batch size,比如实际batch是32,累积4步,相当于128,这样减少显存占用同时保持效果。

模型保存和早停也是必要的,避免训练过久。可以设置验证损失监控,保存最佳模型。

最后,混合精度训练可能可以加快训练速度,用torch.cuda.amp,这对RTX 3060支持良好,同时减少显存占用。

总结一下,调整点包括数据加载的batch size和num_workers,数据增强,处理长尾分布的采样方法或损失函数,优化器选择和学习率策略,分层学习率,损失函数调整,评估指标,训练周期和早停,显存优化措施等。

答复:

Image

Image

Image

Image

Image

Image

所以最终采用的方案:

Image

Image

Image
这里我做了一个小小的修正,你猜在哪里:

Image
准确率几乎为零:

Image

Image

python3.7,这一步没做:

Image

开始训练:

for epoch in range(1, EPOCHS+1):
    
    print(f'Epoch {epoch}/{EPOCHS}')
    
    ## 训练阶段
    model.train()
    for images, labels in tqdm(train_loader): # 获得一个 batch 的数据和标注
        batch_idx += 1
        log_train = train_one_batch(images, labels)
        df_train_log = df_train_log.append(log_train, ignore_index=True)
        # wandb.log(log_train)
        
    lr_scheduler.step()

    ## 测试阶段
    model.eval()
    log_test = evaluate_testset()
    df_test_log = df_test_log.append(log_test, ignore_index=True)
    # wandb.log(log_test)
    
    # 保存最新的最佳模型文件
    if log_test['test_accuracy'] > best_test_accuracy: 
        # 删除旧的最佳模型文件(如有)
        old_best_checkpoint_path = 'checkpoint/best-{:.3f}.pth'.format(best_test_accuracy)
        if os.path.exists(old_best_checkpoint_path):
            os.remove(old_best_checkpoint_path)
        # 保存新的最佳模型文件
        best_test_accuracy = log_test['test_accuracy']
        new_best_checkpoint_path = 'checkpoint/best-{:.3f}.pth'.format(log_test['test_accuracy'])
        torch.save(model, new_best_checkpoint_path)
        print('保存新的最佳模型', 'checkpoint/best-{:.3f}.pth'.format(best_test_accuracy))
        # best_test_accuracy = log_test['test_accuracy']

df_train_log.to_csv('训练日志-训练集.csv', index=False)
df_test_log.to_csv('训练日志-测试集.csv', index=False)

期待:

Image

在这个等待的时候,我再说一下其他的。
在数据处理的图像清洗方面,我这两个分开进行。就是删除GIF和删除非三通道图像这个我分成了两步,异步处理。这样的好处是节约时间。

Image

Image