【PyTorch】深度学习实战(1)——基于主动学习策略处理Mnist分类任务

【PyTorch】深度学习实战(1)——基于主动学习策略处理Mnist分类任务
在这里插入图片描述

🌈 欢迎进入我的个人主页,我是高斯小哥!👈

🎓 博主档案: 广东某985本硕,SCI顶刊一作,深耕深度学习多年,熟练掌握PyTorch框架。

🔧 技术专长: 擅长处理各类深度学习任务,包括但不限于图像分类、图像重构(去雾\去模糊\修复)、目标检测、图像分割、人脸识别、多标签分类、重识别(行人\车辆)、无监督域适应、主动学习、机器翻译、文本分类、命名实体识别、知识图谱、实体对齐、时间序列预测等。业余时间,成功助力数百位用户解决技术难题,深受用户好评。

📝 博客风采: 我坚信知识分享的力量,因此在博客中倾注心血,分享深度学习、PyTorch、Python的优质内容。本年已发表原创文章300+,代码分享次数突破2w+,为广大读者提供了丰富的学习资源和实用解决方案。

💡 服务项目: 提供科研入门辅导(主要是代码方面)、知识答疑、定制化需求解决等服务,助力你的深度学习之旅(有需要可私信联系)。

🌟 期待与你共赴深度学习之旅,书写精彩篇章!感谢关注与支持!🚀


🔥一、引言

  在深度学习的日常实践中,我们经常会遇到标注数据不足的问题。想象一下,如果你有大量的数据需要标注,但时间和预算都有限,你会怎么做? 这时,主动学习就派上用场了。主动学习就像是个聪明的数据挑选员,帮助我们从海量的未标注数据中找出那些对模型提升最有帮助的数据(信息量最大的样本)

  拿Mnist数据集来说,虽然它每个样本都有标签,但我们可以假设其中大部分数据都是未标注的。这就像我们实际项目中遇到的情况:有了一堆数据,但不知道哪些数据最有用。这时,我们就可以用主动学习来模拟这个过程。

  具体来说,我们先用一小部分标注好的数据来训练模型,这就像用有限的资源先做个初步的探索。然后,模型会告诉我们哪些未标注的数据最值得去标注。这样,我们就可以集中力量去标注这些数据,再用它们来进一步训练模型。

  这样做的好处是,我们可以在标注数据有限的情况下,通过选择性地标注最有用的数据,让模型的性能得到更好的提升。这就像是用有限的资源,办成了更多的事情。

  所以,即使Mnist数据集已经标注好了,我们也可以通过模拟未标注数据的场景,来验证主动学习策略的有效性。这样做不仅可以帮助我们更好地理解主动学习的工作原理,还可以为我们在实际项目中应用这一策略提供有益的参考。(现在搞xxx方向的太多了,大家都卷得不行。那咱们就换个思路,降低标注样本的比例,先把基准线降下来。然后再试试主动学习这种新招,看看能不能在样本少的情况下,也保持不错的模型性能。 ------> 创新点

  简而言之,主动学习就像是一个聪明的助手,帮助我们在有限的资源下,找到提升模型性能的最佳路径。

📚二、核心思路

  主动学习的主要思想是,通过某种度量标准(如不确定性、多样性等)来评估未标注样本的信息量,然后选择信息量最大的样本进行标注和训练。在本例中,我们将使用不确定性作为度量标准,即选择模型预测最不确定的样本进行标注。

步骤如下:

  1. 使用初始的20%训练数据训练一个基础模型。
  2. 对未标注的数据进行预测,并计算每个样本的不确定性(例如,使用softmax输出的熵值作为不确定性的度量)。
  3. 选择不确定性最高的样本进行人工标注。
  4. 将标注好的样本添加到训练集中,并重新训练模型。
  5. 重复步骤2-4,直到达到预定的主动学习轮次。

💻三、数据准备

  • 首先,我们需要准备Mnist数据集,并将其划分为初始训练集、主动学习集和测试集。

    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    import torch.optim as optim
    import torchvision
    import torchvision.transforms as transforms
    from torch.utils.data import DataLoader
    from torch.utils.data import Dataset
    
    
    # 数据预处理
    transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
    
    # 加载Mnist数据集
    trainset = torchvision.datasets.MNIST('data/', download=True, train=True, transform=transform)
    testset = torchvision.datasets.MNIST('data/', download=True, train=False, transform=transform)
    
    # 划分初始训练集和主动学习集
    initial_train_size = int(0.2 * len(trainset))
    initial_trainset, active_learning_set = torch.utils.data.random_split(trainset, [initial_train_size,
                                                                                     len(trainset) - initial_train_size])
    
    # 创建数据加载器
    initial_trainloader = DataLoader(initial_trainset, batch_size=64, shuffle=True)
    active_learning_loader = DataLoader(active_learning_set, batch_size=64, shuffle=False)
    testloader = DataLoader(testset, batch_size=64, shuffle=False)
    

🚀四、模型构建与初始训练与测试

  • 接下来,我们定义一个简单的卷积神经网络,并使用初始训练集进行训练。

    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    import torch.optim as optim
    import torchvision
    import torchvision.transforms as transforms
    from torch.utils.data import DataLoader
    from torch.utils.data import Dataset
    
    def train_model(model, criterion, optimizer, dataloader, num_epochs):
        for epoch in range(num_epochs):
            running_loss = 0.0
            for i, data in enumerate(dataloader, 0):
                inputs, labels = data
                optimizer.zero_grad()
                outputs = model(inputs)
                loss = criterion(outputs, labels)
                loss.backward()
                optimizer.step()
                running_loss += loss.item()
            print(f'Epoch {epoch + 1}, Loss: {running_loss / len(dataloader)}')
    
    
    def model_test(testloader, net):
        correct = 0  
        total = 0  
        with torch.no_grad():  
            for data in testloader:
                images, labels = data  
                outputs = net(images) 
                _, predicted = torch.max(outputs.data, 1)  
                total += labels.size(0) 
                correct += (predicted == labels).sum().item()  
        print(f'模型在测试集上的准确率: {100 * correct / total} %')  
    
    class Net(nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.conv1 = nn.Conv2d(1, 32, 3, 1)
            self.conv2 = nn.Conv2d(32, 64, 3, 1)
            self.dropout1 = nn.Dropout2d(0.25)
            self.dropout2 = nn.Dropout2d(0.5)
            self.fc1 = nn.Linear(9216, 128)
            self.fc2 = nn.Linear(128, 10)
    
        def forward(self, x):
            x = self.conv1(x)
            x = nn.functional.relu(x)
            x = self.conv2(x)
            x = nn.functional.relu(x)
            x = nn.functional.max_pool2d(x, 2)
            x = self.dropout1(x)
            x = torch.flatten(x, 1)
            x = self.fc1(x)
            x = nn.functional.relu(x)
            x = self.dropout2(x)
            output = self.fc2(x)
            return output
    
    # 实例化模型和优化器
    net = Net()
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(net.parameters(), lr=0.001)
    
    # 调用train_model函数进行初始训练
    num_epochs = 2
    train_model(net, criterion, optimizer, initial_trainloader, num_epochs)
    
    # 调用model_test函数进行模型测试
    model_test(testloader, net)
    

🔍五、主动学习

  • 现在,我们将实现主动学习的轮次。在每个轮次中,我们将选择不确定性最高的样本进行标注,并更新训练集

    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    import torch.optim as optim
    import torchvision
    import torchvision.transforms as transforms
    from torch.utils.data import DataLoader
    from torch.utils.data import Dataset
    
    # 主动学习
    num_active_learning_rounds = 5 
    for round in range(num_active_learning_rounds):  
        # 选择不确定性最高的样本
        uncertainties = get_uncertainty(net, active_learning_loader)
        indices_to_label = torch.argsort(torch.tensor(uncertainties), descending=True)[:1000]  # 假设每次选择1000个样本
        labeled_dataset = SubsetDataset(active_learning_set, indices_to_label)
    
        # 更新训练集
        updated_trainset = torch.utils.data.ConcatDataset([initial_trainset, labeled_dataset])
        trainloader = DataLoader(updated_trainset, batch_size=64, shuffle=True)
    
        # 重新训练模型
        for epoch in range(num_epochs):
            running_loss = 0.0
            for i, data in enumerate(trainloader, 0):
                inputs, labels = data
                optimizer.zero_grad()
                outputs = net(inputs)
                loss = criterion(outputs, labels)
                loss.backward()
                optimizer.step()
                running_loss += loss.item()
            print(f'Active Learning Round {round + 1}, Epoch {epoch + 1}, Loss: {running_loss / len(trainloader)}')
    

请注意,上面的代码省略了人工标注的部分,因为在实际应用中,你需要手动对选定的样本进行标注。标注完成后,你可以创建一个新的数据集,并将其添加到训练集中。

📊六、模型评估

  • 在每个主动学习轮次完成后,我们可以评估模型在测试集上的性能。

    model_test(testloader, net)
    
  • 完整运行结果:

    Epoch 1, Loss: 0.5884045920473464
    Epoch 2, Loss: 0.19729457123878788
    模型在测试集上的准确率: 95.22 %
    主动学习轮数 1, 训练轮数 1, 损失: 0.23299267939428853
    主动学习轮数 1, 训练轮数 2, 损失: 0.17412331988852398
    模型在测试集上的准确率: 96.36 %
    主动学习轮数 2, 训练轮数 1, 损失: 0.1824034520552731
    主动学习轮数 2, 训练轮数 2, 损失: 0.15039132239625735
    模型在测试集上的准确率: 97.26 %
    主动学习轮数 3, 训练轮数 1, 损失: 0.15068418596980765
    主动学习轮数 3, 训练轮数 2, 损失: 0.12904140655882657
    模型在测试集上的准确率: 97.46 %
    主动学习轮数 4, 训练轮数 1, 损失: 0.13444992155749716
    主动学习轮数 4, 训练轮数 2, 损失: 0.10999879615002439
    模型在测试集上的准确率: 97.53 %
    主动学习轮数 5, 训练轮数 1, 损失: 0.10977201326293688
    主动学习轮数 5, 训练轮数 2, 损失: 0.08832737136924383
    模型在测试集上的准确率: 97.85 %
    

🎉七、总结与展望

  通过本博客的介绍,我们学习了如何使用PyTorch实现基于主动学习策略的Mnist分类任务。通过选择最具信息量的样本进行标注,我们可以有效地提高模型的性能,并减少标注数据的成本

  主动学习是一个充满挑战和机遇的领域,它可以帮助我们更加高效地利用有限的标注数据。在未来的工作中,我们可以尝试使用不同的度量标准来选择最具信息量的样本,例如使用模型的不确定性、预测的置信度或基于委员会的投票等方法。此外,我们还可以探索主动学习与其他技术(如迁移学习、半监督学习等)的结合,以进一步提高模型的性能。

  除了上述的改进,我们还可以通过优化模型的架构、使用更先进的优化算法或调整训练策略来进一步提高模型的分类能力。此外,还可以考虑使用数据增强技术来扩充训练集,增加模型的泛化能力。

  在实际应用中,主动学习还可以用于处理各种领域的分类任务,例如医疗图像分析、自然语言处理或金融风险评估等。通过结合领域知识和主动学习策略,我们可以开发出更加智能、高效的模型,为各行各业带来实际价值。

  总之,主动学习是一个充满潜力和前景的研究方向。通过不断的研究和实践,我们可以不断完善和优化主动学习算法,为机器学习领域的发展贡献更多的力量。在未来的工作中,我们期待看到更多关于主动学习的创新研究和应用实践。

🤝和您交个朋友

亲爱的读者:

您手中的这篇文章,是我心血的结晶,每一个字句都汇聚着我对知识的热忱与对分享的执着。它不仅仅是我深入研究的结果,更是我个人经验的沉淀与感悟的升华。我衷心希望,它能如明灯般照亮您的人生旅程,为您指引前行的方向

在这个信息泛滥的时代,内容创作如同浩渺星海中闪耀的星星,虽微小却璀璨夺目。我深知,每一次的创作都是对自我能力的挑战,也是对读者心灵的触动。因此,我始终怀揣着对内容的敬畏之心,竭尽全力为您呈现最有价值的信息。

如果您在阅读这篇文章时,感受到了它的价值或受到了些许的启发,那么我将感到无比的荣幸。同时,我也怀揣着一个小小的请求,能否请您考虑给予我1元钱的打赏? 这不仅仅是对我创作的认可,更是对我未来努力的鞭策。虽然金额微不足道,但对我而言,它却是前行的动力与源泉。

此外,为了感谢您的支持,我将为您准备一份特别的礼物——该项目的完整代码以及代码行级别的保姆级注释。只需在打赏后通过文章末尾的微信号与博主取得联系,并提供相关打赏截图,您即可获得这份珍贵的资料。

我热爱创作,更热爱与您分享知识的喜悦。您的支持是我继续前行的最大动力,也是我不断追求更高质量内容的坚定信念。

为了方便您的打赏,我为您准备了详细的打赏流程。您只需按照👇👇👇步骤操作,便能轻松完成对我的支持。同时,我也非常期待您的反馈与建议,让我们携手共创更美好的内容世界。

在这里插入图片描述
在此,我衷心感谢您的支持与关注。愿我们的心灵因知识而相通,因分享而更加美好。谢谢您,期待与您共同成长,共享知识的喜悦!

最近更新

  1. TCP协议是安全的吗?

    2024-04-03 11:24:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-03 11:24:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-03 11:24:02       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-03 11:24:02       20 阅读

热门阅读

  1. Flink总结

    2024-04-03 11:24:02       16 阅读
  2. 【m122】webrtc的比较

    2024-04-03 11:24:02       14 阅读
  3. IDEA 宝贝插件

    2024-04-03 11:24:02       16 阅读
  4. IntelliJ IDEA - 快捷键 Win & Mac 对照表

    2024-04-03 11:24:02       14 阅读
  5. openshift和k8s的差别

    2024-04-03 11:24:02       12 阅读
  6. RuoYi单体版Table行内编辑

    2024-04-03 11:24:02       16 阅读
  7. 研究应用推广开源项目——提高软件技术的途径

    2024-04-03 11:24:02       15 阅读