PyTorch训练Celeba

CelebFaces属性数据集(CelebA)是一个大规模的人脸属性数据集,包含超过20万张名人图像,每张图像都有40个属性标注。该数据集中的图像涵盖了大范围的姿态变化和复杂的背景。CelebA具有高度的多样性、大量的数据和丰富的标注信息,包括:

  • 10,177个身份,
  • 202,599张人脸图像,
  • 每张图像有5个标志点位置和40个二进制属性标注。

该数据集可用于以下计算机视觉任务的训练和测试集:人脸属性识别、人脸识别、人脸检测、标志点(或面部部位)定位以及人脸编辑与合成。

1. 安装必要的依赖

如果还没有安装PyTorch和Torchvision,可以通过pip安装:

%pip install torch torchvision

2. 加载CelebA数据集

我们可以通过torchvision.datasets模块轻松获取它。

如果没有数据集且无法通过google drive下载,可以通过这篇notebook关联的数据集下载

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader

# 图像的预处理:缩放到 64x64 大小,并归一化
# 这个变换管道通常用于图像分类任务中的数据预处理步骤。通过调整图像大小、转换为张量和标准化,可以确保输入数据的一致性和模型训练的稳定性。
transform = transforms.Compose([
    transforms.Resize((64, 64)),
    #将图像从 PIL 图像或 numpy 数组转换为 PyTorch 张量,并且会自动将图像的像素值从 [0, 255] 范围缩放到 [0, 1] 范围。
    transforms.ToTensor(),
    #使用给定的均值和标准差对图像进行标准化。这里的均值和标准差分别是 [0.5, 0.5, 0.5],表示对每个通道(RGB)进行标准化。标准化公式为: [ text{output} = frac{text{input} - text{mean}}{text{std}} ] 由于输入的像素值已经被 transforms.ToTensor 缩放到 [0, 1] 范围,标准化后的像素值将被调整到 [-1, 1] 范围。
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])

# 加载 CelebA 数据集,如果google drive可以用,download=True,可以直接下载,也可以自己下载后解压到/root/celeba目录下
root = '/root'
train_dataset = torchvision.datasets.CelebA(root=root, split='train', download=False, transform=transform)
test_dataset = torchvision.datasets.CelebA(root=root, split='test', download=False, transform=transform)

# 创建数据加载器,改大batch_size,在GPU T4下显存使用率没增加?
batch_size = 128
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

# 检查数据加载是否成功
print(f"Number of training samples: {len(train_dataset)}")
print(f"Number of testing samples: {len(test_dataset)}")

3. 定义CNN模型

接下来,我们定义一个简单的卷积神经网络模型,结构可以根据任务的复杂性调整。这里的例子是一个基础的CNN。

3.1 初始化

卷积层:
  • self.conv1:第一个卷积层,输入通道数为 3(RGB 图像),输出通道数为 64,卷积核大小为 3x3,步幅为 1,填充为 1。
  • self.conv2:第二个卷积层,输入通道数为 64,输出通道数为 128,卷积核大小为 3x3,步幅为 1,填充为 1。
  • self.conv3:第三个卷积层,输入通道数为 128,输出通道数为 256,卷积核大小为 3x3,步幅为 1,填充为 1。
全连接层:
  • self.fc1:第一个全连接层,输入大小为 25688,输出大小为 512。
  • self.fc2:第二个全连接层,输入大小为 512,输出大小为 40(CelebA 数据集有 40 个属性标签)。
池化层和激活函数:
  • self.pool:最大池化层,池化核大小为 2x2,步幅为 2。

  • self.relu:ReLU 激活函数。

    class SimpleCNN(nn.Module):
    def init(self):
    super(SimpleCNN, self).init()
    self.conv1 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1)
    self.conv2 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1)
    self.conv3 = nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, stride=1, padding=1)
    self.fc1 = nn.Linear(25688, 512)
    self.fc2 = nn.Linear(512, 40) # CelebA 有 40 个属性标签

          self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
          self.relu = nn.ReLU()
    
      def forward(self, x):
          x = self.relu(self.conv1(x))
          x = self.pool(x)
          x = self.relu(self.conv2(x))
          x = self.pool(x)
          x = self.relu(self.conv3(x))
          x = self.pool(x)
          
          x = x.view(x.size(0), -1)  # 展平操作
          x = self.relu(self.fc1(x))
          x = self.fc2(x)
          
          return x
    

    实例化模型

    model = SimpleCNN()

4. 定义损失函数和优化器

对于多标签分类任务,我们使用 BCEWithLogitsLoss 损失函数。优化器可以选择 Adam 或 SGD。

criterion = nn.BCEWithLogitsLoss()  # 二分类交叉熵损失
optimizer = optim.Adam(model.parameters(), lr=0.001)

5. 训练模型

下面是训练模型的代码,每个 epoch 后对模型进行验证。

5.1. train 函数

train 函数用于训练模型。

参数解释
  • model:要训练的神经网络模型。
  • train_loader:训练数据的 DataLoader 对象。
  • criterion:损失函数,用于计算预测值和真实值之间的误差。
  • optimizer:优化器,用于更新模型的参数。
  • num_epochs:训练的轮数。
  • device:计算设备(如 CPU 或 GPU)。

5.2. evaluate 函数

evaluate 函数用于评估模型的性能。

参数解释
  • model:要评估的神经网络模型。

  • test_loader:测试数据的 DataLoader 对象。

  • criterion:损失函数,用于计算预测值和真实值之间的误差。

  • device:计算设备(如 CPU 或 GPU)。

    def train(model, train_loader, criterion, optimizer, num_epochs, device):
    model.train() #设置模型为训练模式
    for epoch in range(num_epochs):
    for images, labels in train_loader:
    # 将数据移动到选定的设备
    images, labels = images.to(device), labels.to(device).float()

              # 前向传播
              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}')
    

    def evaluate(model, test_loader, criterion, device):
    model.eval() # 设置模型为评估模式
    with torch.no_grad(): # 禁用梯度计算
    total_loss = 0
    correct = 0
    total = 0
    for images, labels in test_loader:
    # 将数据移动到选定的设备
    images, labels = images.to(device), labels.to(device).float()

              # 前向传播
              outputs = model(images)
              # 计算损失,并累加到 total_loss
              loss = criterion(outputs, labels)
              total_loss += loss.item()
              
              # 计算准确率
              predicted = (outputs > 0.5).float()
              total += labels.size(0) * labels.size(1)  # 总标签数
              correct += (predicted == labels).sum().item()
          # 打印平均损失和准确率
          print(f'Average loss: {total_loss / len(test_loader):.4f}, Accuracy: {100 * correct / total:.2f}%')
    
  1. 开始训练

通过调用train函数进行训练,完成后用evaluate函数进行验证。

# 检查 CUDA 是否可用,并选择设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 将模型移动到选定的设备
model = model.to(device)

# 训练模型
train(model, train_loader, criterion, optimizer, num_epochs=10, device=device)

# 验证模型
evaluate(model, test_loader, criterion, device=device)
  1. 保存和加载模型

训练完成后,可以保存模型以便之后使用。

# 保存模型
torch.save(model.state_dict(), 'celeba_cnn.pth')

# 加载模型
model.load_state_dict(torch.load('celeba_cnn.pth'))
相关推荐
weixin_515202491 分钟前
第R4周-LSTM-火灾温度预测
人工智能·rnn·lstm
西猫雷婶4 分钟前
python学opencv|读取图像(二十二)使用cv2.polylines()绘制多边形
开发语言·python·opencv
小任同学Alex7 分钟前
Lagent:从零搭建你的 Multi-Agent
人工智能·自然语言处理·大模型·大语言模型·多模态
伊一大数据&人工智能学习日志7 分钟前
OpenCV计算机视觉 02 图片修改 图像运算 边缘填充 阈值处理
人工智能·opencv·计算机视觉
m0_6938093812 分钟前
Python——day09
python·学习
杀生丸学AI14 分钟前
【三维重建】去除瞬态物体Distractor汇总
人工智能·大模型·aigc·三维重建·扩散模型·高斯泼溅·空间智能
Zhi.C.Yue21 分钟前
SVM理论推导
人工智能·机器学习·支持向量机
愚者大大24 分钟前
线性分类器(KNN,SVM损失,交叉熵损失,softmax)
人工智能·机器学习·支持向量机
极客小张28 分钟前
基于STM32的智慧农业控制系统设计:python可视化、UART、I2C、TCP/HTTP技术
python·stm32·单片机·物联网·tcp/ip·毕业设计·课程设计
魔道不误砍柴功33 分钟前
Java 中反射的高级用法:窥探 Java 世界的魔法之门
java·开发语言·python