主要内容:
- 使用目的(feature normalization/data standardization):使不同特征的数值范围和分布更加一致,从而提高模型的训练效率和测试性能:
- testset 和valset也要进行一致的变化来避免量纲不一致造成的影响等;
- 不能用到整个set(会引入test set/val set的信息)
- 在使用预训练模型时,如何对图像进行归一化处理,以及这种处理方式对模型性能的影响
参考:
- https://discuss.pytorch.org/t/should-we-use-our-normalization-for-training-a-pretrained-model/34905
- https://stackoverflow.com/questions/49444262/normalize-data-before-or-after-split-of-training-and-testing-data
与pretrain model相关的处理
用预训练模型推理
- 直接使用预训练模型:如果只是想直接在自己的图像上使用预训练模型进行推理(即直接使用模型进行预测,而不是进一步训练),则需要将图像归一化到与 ImageNet 数据集相同的统计特性(stats)上。因为预训练模型是在 ImageNet 数据集上训练的,它已经学习到了 ImageNet 数据集的特征和分布。通过将图像归一化到 ImageNet 的统计特性上,可以使模型更好地理解和处理图像,从而提高预测的准确性。
- 输出类别限制:不过,这样做会有一个限制,即模型的输出类别将局限于 ImageNet 数据集中的类别。ImageNet 数据集包含了大约 1000 个类别,如果图像属于这些类别之一,那么模型可以正确识别;但如果图像属于其他类别,模型可能无法准确识别,因为模型没有学习过这些类别的特征。
微调预训练模型
- 微调的必要性:如果想要让预训练模型适应特定任务或数据集(即图像类别与 ImageNet 类别不同,或者有特定的图像特征需要模型学习),则需要对预训练模型进行微调(finetune)。微调是指在预训练模型的基础上,使用自己的数据集继续训练模型,使其更好地适应自己的数据。
- 使用自己的统计数据进行归一化:在微调过程中,建议使用自己的数据集的统计特性来对图像进行归一化。因为自己的数据集可能与 ImageNet 数据集在分布、特征等方面存在差异,或者使用能可以更好地反映数据集特性的统计数据,从而使模型在微调过程中更有效地学习和适应数据。
- 数据集差异的影响:存在过两个数据集之间存在很大差异的情况,使得这种差异对模型的性能产生了巨大的影响。说明在不同数据集之间,数据的分布和特征差异可能会对模型的学习和预测产生显著的影响。然而,对于非常小的数据集差异,不确定其影响程度,可能需要更多的实验和分析来确定.
代码示例
直接使用预训练模型进行推理
import torch
import torchvision
import torchvision.transforms as transforms
from PIL import Image# 加载预训练模型
model = torchvision.models.resnet50(pretrained=True)# 定义归一化参数,使用 ImageNet 的均值和标准差
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])# 定义图像预处理流程
transform = transforms.Compose([transforms.Resize(256), # 将图像大小调整为 256x256transforms.CenterCrop(224), # 从图像中心裁剪出 224x224 的区域transforms.ToTensor(), # 将 PIL 图像转换为 PyTorch 张量normalize # 使用 ImageNet 的统计数据进行归一化
])# 加载图像
image_path = 'path/to/your/image.jpg'
image = Image.open(image_path)# 对图像进行预处理
preprocessed_image = transform(image)# 将预处理后的图像添加一个批次维度,以匹配模型的输入要求
preprocessed_image = preprocessed_image.unsqueeze(0)# 将模型设置为评估模式
model.eval()# 使用预训练模型进行推理
with torch.no_grad():output = model(preprocessed_image)# 输出预测结果
print(output)
微调预训练模型
import torch
import torchvision
import torchvision.transforms as transforms
from PIL import Image
from torch.utils.data import DataLoader, Dataset
import numpy as np# 加载预训练模型
model = torchvision.models.resnet50(pretrained=True)# 假设你有一个自定义数据集类
class CustomDataset(Dataset):def __init__(self, image_paths, labels, transform=None):self.image_paths = image_pathsself.labels = labelsself.transform = transformdef __len__(self):return len(self.image_paths)def __getitem__(self, index):image_path = self.image_paths[index]image = Image.open(image_path)label = self.labels[index]if self.transform:image = self.transform(image)return image, label# 计算自定义数据集的均值和标准差
def calculate_dataset_statistics(dataset):data_loader = DataLoader(dataset, batch_size=1, shuffle=False)mean = torch.zeros(3)std = torch.zeros(3)for images, _ in data_loader:for i in range(3):mean[i] += images[:, i, :, :].mean()std[i] += images[:, i, :, :].std()mean.div_(len(dataset))std.div_(len(dataset))return mean, std# 创建自定义数据集实例
image_paths = ['path/to/image1.jpg', 'path/to/image2.jpg', ...]
labels = [0, 1, ...] # 假设标签是整数
custom_dataset = CustomDataset(image_paths, labels)# 计算自定义数据集的均值和标准差
custom_mean, custom_std = calculate_dataset_statistics(custom_dataset)# 定义归一化参数,使用自定义数据集的均值和标准差
normalize = transforms.Normalize(mean=custom_mean.tolist(),std=custom_std.tolist())# 定义图像预处理流程
transform = transforms.Compose([transforms.Resize(256), # 将图像大小调整为 256x256transforms.CenterCrop(224), # 从图像中心裁剪出 224x224 的区域transforms.ToTensor(), # 将 PIL 图像转换为 PyTorch 张量normalize # 使用自定义数据集的统计数据进行归一化
])# 更新自定义数据集实例的预处理流程
custom_dataset.transform = transform# 创建数据加载器
data_loader = DataLoader(custom_dataset, batch_size=32, shuffle=True)# 将模型设置为训练模式
model.train()# 定义损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# 微调预训练模型
for epoch in range(10): # 假设训练 10 个周期for images, labels in data_loader:optimizer.zero_grad()output = model(images)loss = criterion(output, labels)loss.backward()optimizer.step()
-
第一个示例中,直接使用预训练模型进行推理,图像归一化使用的是 ImageNet 的统计数据,这样可以使模型更好地理解和处理图像,提高预测的准确性。
-
第二个示例中,对预训练模型进行微调,图像归一化使用的是自定义数据集的统计数据,这样可以使模型更好地适应自定义数据集的特征和分布,提高模型在特定任务上的性能。