• 【迁移学习】迁移学习的基本概念与应用


    迁移学习

    • 迁移学习的基本概念与应用

    引言

    迁移学习是一种机器学习技术,旨在将从一个领域中学到的知识应用到另一个相关领域中,以解决目标任务的训练数据不足和模型训练时间过长的问题。它在计算机视觉、自然语言处理等领域中得到了广泛应用。本文将详细介绍迁移学习的基本概念、常见方法及其在实际应用中的具体案例。

    提出问题

    1. 什么是迁移学习?
    2. 迁移学习有哪些常见方法?
    3. 如何在实际项目中应用迁移学习提高模型性能?

    解决方案

    迁移学习的基本概念

    迁移学习(Transfer Learning)是指将一个领域中学到的模型参数、特征表示或知识应用到另一个领域,以提升目标任务的学习效果。传统机器学习和深度学习方法通常需要大量标注数据进行训练,而迁移学习通过利用预训练模型,可以在较少标注数据的情况下取得良好的性能。

    迁移学习的常见方法

    微调预训练模型(Fine-Tuning)

    微调预训练模型是迁移学习中最常用的方法之一。首先,在大规模数据集(如ImageNet)上预训练一个深度神经网络,然后将其应用到目标任务中,通过在目标任务数据上继续训练模型,以适应新的任务需求。

    特征提取(Feature Extraction)

    特征提取方法是指利用预训练模型的特征提取能力,将其作为固定的特征提取器,然后在提取的特征基础上训练一个新的分类器或回归器。

    域自适应(Domain Adaptation)

    域自适应方法旨在解决源领域和目标领域分布差异较大的问题。通过学习一个共享的特征表示,使得在源领域和目标领域的特征分布尽可能一致,从而提升目标任务的性能。

    在实际项目中应用迁移学习

    使用微调预训练模型进行图像分类

    以下示例展示了如何使用微调预训练的 ResNet 模型进行图像分类任务。

    import torch
    import torch.nn as nn
    import torch.optim as optim
    from torchvision import datasets, models, transforms
    
    # 数据预处理
    data_transforms = {
        'train': transforms.Compose([
            transforms.RandomResizedCrop(224),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
        ]),
        'val': transforms.Compose([
            transforms.Resize(256),
            transforms.CenterCrop(224),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
        ]),
    }
    
    data_dir = 'data/hymenoptera_data'
    image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ['train', 'val']}
    dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=32, shuffle=True, num_workers=4) for x in ['train', 'val']}
    dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}
    class_names = image_datasets['train'].classes
    
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    
    # 加载预训练的 ResNet 模型
    model_ft = models.resnet18(pretrained=True)
    
    # 修改最后的全连接层以适应新的分类任务
    num_ftrs = model_ft.fc.in_features
    model_ft.fc = nn.Linear(num_ftrs, len(class_names))
    
    model_ft = model_ft.to(device)
    
    # 定义损失函数和优化器
    criterion = nn.CrossEntropyLoss()
    optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)
    exp_lr_scheduler = optim.lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)
    
    # 训练和评估模型
    def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
        for epoch in range(num_epochs):
            print(f'Epoch {epoch}/{num_epochs - 1}')
            print('-' * 10)
    
            for phase in ['train', 'val']:
                if phase == 'train':
                    model.train()
                else:
                    model.eval()
    
                running_loss = 0.0
                running_corrects = 0
    
                for inputs, labels in dataloaders[phase]:
                    inputs = inputs.to(device)
                    labels = labels.to(device)
    
                    optimizer.zero_grad()
    
                    with torch.set_grad_enabled(phase == 'train'):
                        outputs = model(inputs)
                        _, preds = torch.max(outputs, 1)
                        loss = criterion(outputs, labels)
    
                        if phase == 'train':
                            loss.backward()
                            optimizer.step()
    
                    running_loss += loss.item() * inputs.size(0)
                    running_corrects += torch.sum(preds == labels.data)
    
                if phase == 'train':
                    scheduler.step()
    
                epoch_loss = running_loss / dataset_sizes[phase]
                epoch_acc = running_corrects.double() / dataset_sizes[phase]
    
                print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')
    
            print()
    
        return model
    
    model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler, num_epochs=25)
    
    使用特征提取进行文本分类

    以下示例展示了如何使用特征提取方法将预训练的 BERT 模型应用于文本分类任务。

    from transformers import BertTokenizer, BertModel
    import torch
    import torch.nn as nn
    import torch.optim as optim
    from torch.utils.data import DataLoader, Dataset
    
    class TextDataset(Dataset):
        def __init__(self, texts, labels, tokenizer, max_len):
            self.texts = texts
            self.labels = labels
            self.tokenizer = tokenizer
            self.max_len = max_len
    
        def __len__(self):
            return len(self.texts)
    
        def __getitem__(self, item):
            text = self.texts[item]
            label = self.labels[item]
            encoding = self.tokenizer.encode_plus(
                text,
                add_special_tokens=True,
                max_length=self.max_len,
                return_token_type_ids=False,
                padding='max_length',
                truncation=True,
                return_attention_mask=True,
                return_tensors='pt',
            )
            return {
                'text': text,
                'input_ids': encoding['input_ids'].flatten(),
                'attention_mask': encoding['attention_mask'].flatten(),
                'label': torch.tensor(label, dtype=torch.long)
            }
    
    class TextClassifier(nn.Module):
        def __init__(self, n_classes):
            super(TextClassifier, self).__init__()
            self.bert = BertModel.from_pretrained('bert-base-uncased')
            self.drop = nn.Dropout(p=0.3)
            self.out = nn.Linear(self.bert.config.hidden_size, n_classes)
    
        def forward(self, input_ids, attention_mask):
            pooled_output = self.bert(
                input_ids=input_ids,
                attention_mask=attention_mask
            )[1]
            output = self.drop(pooled_output)
            return self.out(output)
    
    # 数据准备
    tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
    texts = ["example text 1", "example text 2"]
    labels = [0, 1]
    dataset = TextDataset(texts, labels, tokenizer, max_len=128)
    dataloader = DataLoader(dataset, batch_size=2)
    
    # 初始化模型
    model = TextClassifier(n_classes=2)
    model = model.to(device)
    
    # 定义损失函数和优化器
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=2e-5)
    
    # 训练模型
    for epoch in range(3):
        model.train()
        for batch in dataloader:
            input_ids = batch['input_ids'].to(device)
            attention_mask = batch['attention_mask'].to(device)
            labels = batch['label'].to(device)
    
            outputs = model(input_ids=input_ids, attention_mask=attention_mask)
            loss = criterion(outputs, labels)
    
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
    
            print(f'Epoch {epoch}, Loss: {loss.item()}')
    

    通过上述方法,可以充分利用迁移学习的优势,在较少数据和计算资源的情况下,快速构建和优化深度学习模型。迁移学习在计算机视觉、自然语言处理等领域中具有广泛的应用前景,能够帮助开发者有效提升模型性能,实现更复杂的任务。

  • 相关阅读:
    springboot - 2.7.3版本 - (二)整合Redis
    Embedding技术与应用(4): Embedding应用工程探析
    MySQL知识【可视化软件navicat安装&使用】第五章
    vue 语法--表单取值,组件通信
    第五章 多态
    Css3新布局---Grid网格
    纯C++自动识别设备串口
    彻底解决electron-builder安装问题与npm下载配置问题
    交换机端口安全实验
    许战海战略文库|隆基绿能,光伏龙头如何走出战略无人区?
  • 原文地址:https://blog.csdn.net/weixin_39372311/article/details/140971322