欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 深度学习:迁移学习

深度学习:迁移学习

2025/4/25 17:50:38 来源:https://blog.csdn.net/ycy200377/article/details/147492024  浏览:    关键词:深度学习:迁移学习

迁移学习

标题1.什么是迁移学习

迁移学习(Transfer Learning)是一种机器学习方法,就是把为任务 A 开发 的模型作为初始点,重新使用在为任务 B 开发模型的过程中。迁移学习是通过 从已学习的相关任务中转移知识来改进学习的新任务,虽然大多数机器学习算 法都是为了解决单个任务而设计的,但是促进迁移学习的算法的开发是机器学 习社区持续关注的话题。 迁移学习对人类来说很常见,例如,我们可能会发现 学习识别苹果可能有助于识别梨,或者学习弹奏电子琴可能有助于学习钢琴。
找到目标问题的相似性,迁移学习任务就是从相似性出发,将旧领域 (domain)学习过的模型应用在新领域上

标题2.迁移学习的步骤

1、选择预训练的模型和适当的层
通常,我们会选择在大规模图像数据集(如ImageNet)上预训练的模型,如VGG、ResNet等。然后,根据新数据集的特点,选择需要微调的模型层。对于低级特征的任务(如边缘检测),最好使用浅层模型的层,而对于高级特征的任务(如分类),则应选择更深层次的模型。
2、冻结预训练模型的参数
保持预训练模型的权重不变,只训练新增加的层或者微调一些层,避免因为在数据集中过拟合导致预训练模型过度拟合。
3、在新数据集上训练新增加的层
在冻结预训练模型的参数情况下,训练新增加的层。这样,可以使新模型适应新的任务,从而获得更高的性能。
4、微调预训练模型的层
在新层上进行训练后,可以解冻一些已经训练过的层,并且将它们作为微调的目标。这样做可以提高模型在新数据集上的性能。
5、评估和测试
在训练完成之后,使用测试集对模型进行评估。如果模型的性能仍然不够好,可以尝试调整超参数或者更改微调层。

标题3.迁移学习实例

该实例使用的模型是ResNet-18残差神经网络模型
###1. 导入必要的库

import torch
import torchvision.models as models
from torch import nn
from torch.utils.data import Dataset,DataLoader
from torchvision import transforms
from PIL import Image
import numpy as np

这里导入了后续代码会用到的库,具体如下:
torch:PyTorch 深度学习框架的核心库。
torchvision.models:包含了预训练的模型,这里会用到 ResNet-18。
torch.nn:用于构建神经网络的模块。
torch.utils.data.Dataset 和 torch.utils.data.DataLoader:用于自定义数据集和加载数据。
torchvision.transforms:用于图像的预处理。
PIL.Image:用于读取图像。
numpy:用于数值计算。
###2. 加载预训练模型并修改全连接层

resnet_model= models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
for param in resnet_model.parameters():print(param)param.requires_grad=False
in_features=resnet_model.fc.in_features
resnet_model.fc=nn.Linear(in_features,20)
params_to_update=[]
for param in resnet_model.parameters():if param.requires_grad==True:params_to_update.append(param)

加载预训练的 ResNet-18 模型。
把模型中所有参数的 requires_grad 设置为 False,也就是冻结这些参数,使其在训练时不更新。
获取原模型全连接层的输入特征数,然后将全连接层替换为一个新的全连接层,输出维度为 20。
收集所有 requires_grad 为 True 的参数,这些参数会在训练时更新。
###3. 定义图像预处理变换

data_transforms = {'train':transforms.Compose([transforms.Resize([300,300]),transforms.RandomRotation(45),transforms.CenterCrop(224),transforms.RandomHorizontalFlip(p=0.5),transforms.RandomVerticalFlip(p=0.5),transforms.RandomGrayscale(p=0.1),transforms.ToTensor(),transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])]),'valid':transforms.Compose([transforms.Resize([224,224]),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),
}

定义了两个图像预处理的组合变换,分别用于训练集和验证集。
训练集的变换包含了数据增强操作,像随机旋转、水平翻转、垂直翻转等。
验证集的变换只包含了调整大小、转换为张量和标准化操作。

4. 自定义数据集类

class food_dataset(Dataset):def __init__(self,file_path,transform=None):self.file_path = file_pathself.imgs = []self.labels = []self.transform = transformwith open(self.file_path) as f:samples = [x.strip().split(' ') for x in f.readlines()]for img_path,label in samples:self.imgs.append(img_path)self.labels.append(label)def __len__(self):return  len(self.imgs)def __getitem__(self, idx):image = Image.open(self.imgs[idx])if self.transform:image = self.transform(image)label = self.labels[idx]label = torch.from_numpy(np.array(label,dtype=np.int64))return image,label

自定义了一个 food_dataset 类,继承自 torch.utils.data.Dataset。 init 方法:解析包含图像路径和标签的文本文件,把图像路径和标签分别存到 self.imgs 和 self.labels 中。
len 方法:返回数据集的大小。
getitem 方法:根据索引读取图像,对图像进行预处理,将标签转换为张量,然后返回图像和标签。

5. 创建数据集和数据加载器

training_data = food_dataset(file_path='./trainbig.txt',transform=data_transforms['train'])
test_data = food_dataset(file_path='./testbig.txt',transform=data_transforms['valid'])
train_dataloader = DataLoader(training_data,batch_size=64,shuffle=True)
test_dataloader = DataLoader(test_data,batch_size=64,shuffle=True)

创建训练集和测试集的数据集对象。
创建训练集和测试集的数据加载器,设置批量大小为 64,并且打乱数据
###6. 配置训练设备、损失函数、优化器和学习率调度器

device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")
model=resnet_model.to(device)
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(params_to_update,lr=0.001)
scheduler=torch.optim.lr_scheduler.StepLR(optimizer,step_size=5,gamma=0.5)

选择合适的训练设备(GPU 或 CPU)。
把模型移动到所选设备上。
定义交叉熵损失函数。
定义 Adam 优化器,只对之前收集的需要更新的参数进行优化。
定义学习率调度器,每 5 个 epoch 将学习率乘以 0.5。
###7. 定义训练和测试函数

def train(dataloader,model,loss_fn,optimizer):model.train()batch_size_num = 1for X,y in dataloader:X,y = X.to(device),y.to(device)pred = model.forward(X)loss = loss_fn(pred,y)optimizer.zero_grad()loss.backward()optimizer.step()def test(dataloader, model,loss_fn):global best_accsize = len(dataloader.dataset)num_batches =len(dataloader)model.eval()test_loss,correct =0,0with torch.no_grad():for X, y in dataloader:X,y = X.to(device),y.to(device)pred = model.forward(X)test_loss+=loss_fn(pred,y).item()correct += (pred.argmax(1) == y).type(torch.float).sum().item()test_loss /= num_batchescorrect /= sizeprint(f"Test result:\n Accuracy:{(100 * correct)}%, Avg loss: {test_loss}")acc_s.append(correct)loss_s.append(test_loss)if correct>best_acc:best_acc=correct

train 函数:将模型设置为训练模式,遍历训练数据加载器,计算损失,反向传播并更新模型参数。
test 函数:将模型设置为评估模式,遍历测试数据加载器,计算测试集的准确率和平均损失,记录最佳准确率。
8. 训练模型并保存

epochs = 20
acc_s = []
loss_s =[]
for t in range(epochs):print(f"Epoch {t + 1}\n-----------")train(train_dataloader, model,loss_fn, optimizer)scheduler.step()test(test_dataloader,model,loss_fn)
print('最优训练结果为:',best_acc)
torch.save(model.state_dict(), 'food_classification_model.pt')

训练模型 20 个 epoch。
每个 epoch 结束后,更新学习率并进行测试。
打印最优训练结果。
保存模型的参数到 food_classification_model.pt 文件中。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词