当前位置: 首页> 游戏> 单机 > 自监督学习和对比学习举例讲解(附代码)

自监督学习和对比学习举例讲解(附代码)

时间:2025/7/13 13:03:00来源:https://blog.csdn.net/kiritobryant/article/details/140391203 浏览次数:0次

自监督学习与对比学习详解

自监督学习 (Self-Supervised Learning)

例子:图像旋转预测

自监督学习的一个简单例子是图像旋转预测任务。在这个任务中,我们对输入图像进行随机旋转,然后要求模型预测图像旋转的角度。这种方式不需要手动标注数据,因为旋转的角度是已知的。

代码示例

import torch
import torch.nn as nn
import torchvision.transforms as transforms
from torch.utils.data import DataLoader, Dataset
from torchvision.datasets import CIFAR10
import random# 创建自定义数据集
class RotatedCIFAR10(Dataset):def __init__(self, root, train=True, transform=None, download=False):self.dataset = CIFAR10(root=root, train=train, transform=transform, download=download)self.rotations = [0, 90, 180, 270]  # 定义旋转角度def __len__(self):return len(self.dataset)def __getitem__(self, index):img, _ = self.dataset[index]  # 忽略原始标签rotation = random.choice(self.rotations)  # 随机选择一个旋转角度rotated_img = transforms.functional.rotate(img, rotation)  # 对图像进行旋转return rotated_img, rotation // 90  # 返回旋转后的图像和旋转角度的标签(0, 1, 2, 3)# 定义简单的CNN模型
class SimpleCNN(nn.Module):def __init__(self, num_classes=4):  # 旋转角度分类为4类super(SimpleCNN, self).__init__()self.conv = nn.Sequential(nn.Conv2d(3, 32, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(2),nn.Conv2d(32, 64, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(2))self.fc = nn.Sequential(nn.Linear(64*8*8, 128),nn.ReLU(),nn.Linear(128, num_classes))def forward(self, x):x = self.conv(x)x = x.view(x.size(0), -1)x = self.fc(x)return x# 超参数和数据准备
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = RotatedCIFAR10(root='./data', train=True, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)# 模型、损失函数和优化器
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = SimpleCNN().to(device)
criterion = nn.CrossEntropyLoss()  # 使用交叉熵损失函数进行分类
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# 训练模型
num_epochs = 10
for epoch in range(num_epochs):for images, labels in train_loader:images, labels = images.to(device), labels.to(device)outputs = model(images)  # 前向传播loss = criterion(outputs, labels)  # 计算损失optimizer.zero_grad()loss.backward()  # 反向传播optimizer.step()  # 优化更新print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

解释

  1. 自定义数据集:

    • RotatedCIFAR10类继承自Dataset,用于加载旋转后的CIFAR-10数据集。
    • __getitem__方法随机选择旋转角度并返回旋转后的图像和相应的标签。
    • 这种方式使得我们能够使用旋转角度作为标签进行训练,而不需要人工标注数据。这就是自监督学习的体现。
  2. 简单的CNN模型:

    • SimpleCNN类定义了一个简单的卷积神经网络,用于分类旋转后的图像。
    • forward方法实现前向传播。
  3. 训练过程:

    • 使用DataLoader加载数据。
    • 定义损失函数和优化器。
    • 在训练循环中进行前向传播、计算损失、反向传播和参数更新。

对比学习 (Contrastive Learning)

例子:Siamese Network

对比学习的一个常见例子是Siamese网络。该网络由两个共享权重的子网络组成,分别处理一对输入图像。目标是最小化相似图像之间的距离,最大化不同图像之间的距离。

代码示例

import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
from torch.utils.data import DataLoader, Dataset
from torchvision.datasets import CIFAR10
import random# 创建自定义数据集
class SiameseCIFAR10(Dataset):def __init__(self, root, train=True, transform=None, download=False):self.dataset = CIFAR10(root=root, train=train, transform=transform, download=download)def __len__(self):return len(self.dataset)def __getitem__(self, index):img1, label1 = self.dataset[index]# 随机选择一个图像,可能是相同类也可能是不同类index2 = random.randint(0, len(self.dataset) - 1)img2, label2 = self.dataset[index2]label = torch.tensor(int(label1 == label2), dtype=torch.float32)  # 标签为1表示相同类,0表示不同类return img1, img2, label# 定义Siamese Network
class SiameseNetwork(nn.Module):def __init__(self):super(SiameseNetwork, self).__init__()self.conv = nn.Sequential(nn.Conv2d(3, 32, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(2),nn.Conv2d(32, 64, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(2))self.fc = nn.Sequential(nn.Linear(64*8*8, 128),nn.ReLU(),nn.Linear(128, 128))def forward_once(self, x):x = self.conv(x)x = x.view(x.size(0), -1)x = self.fc(x)return xdef forward(self, x1, x2):out1 = self.forward_once(x1)out2 = self.forward_once(x2)return out1, out2# 对比损失函数
class ContrastiveLoss(nn.Module):def __init__(self, margin=1.0):super(ContrastiveLoss, self).__init__()self.margin = margindef forward(self, output1, output2, label):euclidean_distance = F.pairwise_distance(output1, output2)loss_contrastive = torch.mean((1 - label) * torch.pow(euclidean_distance, 2) +label * torch.pow(torch.clamp(self.margin - euclidean_distance, min=0.0), 2))return loss_contrastive# 超参数和数据准备
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = SiameseCIFAR10(root='./data', train=True, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)# 模型、损失函数和优化器
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = SiameseNetwork().to(device)
criterion = ContrastiveLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# 训练模型
num_epochs = 10
for epoch in range(num_epochs):for img1, img2, labels in train_loader:img1, img2, labels = img1.to(device), img2.to(device), labels.to(device)output1, output2 = model(img1, img2)loss = criterion(output1, output2, labels)optimizer.zero_grad()loss.backward()optimizer.step()print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

解释

  1. 自定义数据集:

    • SiameseCIFAR10类继承自Dataset,用于加载图像对。
    • __getitem__方法返回图像对及其相似性标签。
  2. Siamese网络:

    • SiameseNetwork类定义了一个共享权重的卷积神经网络,用于处理图像对。
    • forward_once方法处理单个图像,forward方法处理图像对。
  3. 对比损失函数:

    • ContrastiveLoss类定义了对比损

失函数。

  • forward方法计算两个输出之间的欧氏距离,并根据相似性标签计算损失。
  1. 训练过程:
    • 使用DataLoader加载数据。
    • 定义损失函数和优化器。
    • 在训练循环中进行前向传播、计算损失、反向传播和参数更新。

总结

自监督学习和对比学习都是利用无标签数据进行训练的方法。自监督学习通过设计预训练任务生成标签,而对比学习通过最小化相似样本之间的距离和最大化不同样本之间的距离来学习有用的特征。上面的例子详细展示了如何实现这两种学习方法,希望能帮助各位更好的理解。

关键字:自监督学习和对比学习举例讲解(附代码)

版权声明:

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

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

责任编辑: