【深度学习 Transformer】训练 Vision Transformer (ViT) 进行图像分类:不使用预训练模型

在深度学习领域,预训练模型已经成为提高模型性能和减少训练时间的重要手段。然而,有时候我们可能需要从头开始训练模型,以便更好地适应特定的数据集或者学习任务。本文将介绍如何从零开始训练 Vision Transformer (ViT) 模型进行图像分类任务。

Vision Transformer 简介

Vision Transformer (ViT) 是一种将自然语言处理中大放异彩的 Transformer 架构应用于计算机视觉任务的模型。ViT 通过将图像分割成多个小块(patches),然后将这些小块视为序列数据输入到 Transformer 模型中,从而实现对图像的分类和其他视觉任务。

环境准备

在开始之前,请确保您的环境中安装了以下库:

  • PyTorch
  • torchvision
  • transformers
  • PIL 或其他图像处理库

您可以通过 pip 安装这些库:

pip install torch torchvision transformers pillow

数据预处理

在训练模型之前,我们需要对图像数据进行预处理。这通常包括调整图像大小、随机翻转、旋转等操作,以增加数据的多样性并防止模型过拟合。

from torchvision import transforms

transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.RandomHorizontalFlip(),
    transforms.RandomVerticalFlip(),
    transforms.RandomRotation(20),
    transforms.ToTensor(),
])

加载数据集

我们将使用 ImageFolder 来加载数据集,并将其分为训练集和测试集。

from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader

train_dataset = ImageFolder(root='path_to_train_dataset', transform=transform)
test_dataset = ImageFolder(root='path_to_test_dataset', transform=transform)

train_loader = DataLoader(dataset=train_dataset, batch_size=16, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=16, shuffle=False)

初始化 Vision Transformer 模型

我们将初始化一个 ViT 模型,不加载任何预训练权重。我们还需要修改模型的分类器层,以适应我们的二分类任务。

from transformers import ViTForImageClassification, ViTConfig

config = ViTConfig(
    num_hidden_layers=12,
    num_attention_heads=12,
    intermediate_size=3072,
    hidden_size=768,
    num_classes=2  # 二分类
)

model = ViTForImageClassification(config)

训练模型

接下来,我们将定义损失函数、优化器和学习率调度器,并开始训练模型。

import torch
import torch.nn as nn
import torch.optim as optim

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

criterion = nn.CrossEntropyLoss()
optimizer = optim.AdamW(model.parameters(), lr=0.0001)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)

# 训练循环
for epoch in range(20):
    # 训练过程...

测试模型

在训练完成后,我们将在测试集上评估模型的性能。

model.eval()
# 测试过程...

保存模型

最后,我们将模型的权重保存到文件中,以便将来使用。

torch.save(model.state_dict(), 'path_to_save_model/transformer_model.pth')

结论

从头开始训练 Vision Transformer 模型可以让我们更好地控制模型的学习过程,并完全适应我们的特定任务。虽然这可能需要更多的时间和计算资源,但有时这是获得最佳性能的必要步骤。

通过本文的介绍,您应该能够理解并实现一个不使用预训练权重的 ViT 模型。开始训练您自己的模型,并探索深度学习在图像分类任务中的潜力吧!

transformer_train.py

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms
from torch.utils.data import DataLoader
from transformers import ViTFeatureExtractor, ViTForImageClassification, ViTConfig
from torchvision.datasets import ImageFolder
import warnings
warnings.filterwarnings('ignore')

# 设置超参数
batch_size = 16
learning_rate = 0.0001
num_epochs = 20
num_classes = 2  # 二分类

# 数据预处理
transform = transforms.Compose([
    transforms.Resize((224, 224)),  # 调整图像大小以适应ViT模型
    transforms.RandomHorizontalFlip(),
    transforms.RandomVerticalFlip(),
    transforms.RandomRotation(20),
    transforms.ToTensor(),
])

# 加载数据集
train_dataset = ImageFolder(root='E:/PycharmProject/LargeSoilDetection/datasets/train/', transform=transform)
test_dataset = ImageFolder(root='E:/PycharmProject/LargeSoilDetection/datasets/test/', transform=transform)

# 创建数据加载器
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

# 初始化ViT模型配置
config = ViTConfig()
config.num_hidden_layers = 12  # 您可以根据需要调整模型大小
config.num_attention_heads = 12
config.intermediate_size = 3072
config.hidden_size = 768
config.num_classes = num_classes  # 设置正确的类别数

# 初始化模型
model = ViTForImageClassification(config)

# 损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.AdamW(model.parameters(), lr=learning_rate)
# 学习率衰减
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)

# 训练模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)
model.to(device)

for epoch in range(num_epochs):
    model.train()
    running_loss = 0.0
    for images, labels in train_loader:
        images = images.to(device)
        labels = labels.to(device)

        # 前向传播
        outputs = model(images)
        loss = criterion(outputs.logits, labels)

        # 反向传播和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        scheduler.step()

        running_loss += loss.item()

    epoch_loss = running_loss / len(train_loader)
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.4f}')

# 测试模型
model.eval()
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        _, predicted = torch.max(outputs.logits, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

accuracy = 100 * correct / total
print(f'Accuracy of the model on the test images: {accuracy:.2f}%')

# 保存模型
torch.save(model.state_dict(), './model/transformer_model2.pth')
<think>嗯,用户问的是ViT训练时默认的数据是否是float32。首先,我需要确认ViTVision Transformer)的基本训练设置。ViT通常使用PyTorch或TensorFlow这样的深度学习框架来实现。在PyTorch中,默认的浮点类型是float32,也就是单精度浮点数。TensorFlow的情况可能类似,但需要具体确认。 接下来,用户可能关心的是为什么使用float32而是其他精度,比如float16或者bfloat16。可能的原因包括训练稳定性,因为float32的动态范围更大,减少梯度消失或爆炸的问题。过,混合精度训练现在也很常见,尤其是使用float16加上动态缩放梯度,或者bfloat16来保持数值稳定性同时节省内存。 另外,用户可能没有直接提到,但潜在的问题可能是关于训练效率和内存使用使用float32需要更多的显存,而降低精度可以加速训练并减少内存消耗。所以用户可能想知道是否有必要调整默认设置,或者是否在特定情况下应该使用同的精度。 还要考虑框架的默认行为是否有变化。例如,PyTorch从某个版本开始是否默认启用了自动混合精度?需要核实最新的文档,确保回答的准确性。 最后,用户可能需要实际应用中的建议,比如什么时候应该坚持使用float32,什么时候可以尝试混合精度训练。这时候需要建议他们根据硬件条件和模型规模来决定,并注意验证训练的稳定性。</think>Vision TransformerViT)的训练中,默认使用的数据类型通常是**float32**(单精度浮点数),但具体情况可能因框架和实际设置而有所同。以下是分步说明: --- ### 1. **框架默认行为** - **PyTorch**:默认张量类型为`torch.float32`,因此在显式指定的情况下,ViT模型的权重和输入数据会自动使用float32。 - **TensorFlow**:同样默认使用`float32`,但可通过`tf.keras.mixed_precision`模块启用混合精度训练。 --- ### 2. **为何常用float32?** - **数值稳定性**:float32的精度(约7位有效数字)和动态范围(指数位8位)更适合深度学习中的梯度计算,避免因精度足导致的训练发散。 - **兼容性**:大多数优化器(如Adam)和层(如LayerNorm)的设计基于float32假设。 --- ### 3. **混合精度训练的例外** 为了提升训练速度和节省显存,**混合精度训练**(float16 + float32)逐渐成为常见选择: - **操作方法**: - PyTorch:使用`torch.cuda.amp.autocast`自动转换部分计算到float16。 - TensorFlow:通过`policy = tf.keras.mixed_precision.Policy('mixed_float16')`设置。 - **注意事项**: - 需配合梯度缩放(Gradient Scaling)避免下溢出。 - 最终权重仍以float32存储,保证推理稳定性。 --- ### 4. **硬件的影响** - **GPU支持**:现代GPU(如NVIDIA Volta及后续架构)对float16有加速支持,混合精度可提升吞吐量。 - **TPU**:Google TPU默认使用bfloat16,但框架会自动转换为float32计算。 --- ### 5. **手动设置数据类型示例(PyTorch)** ```python # 强制使用float32(默认无需设置) model = ViT().to(torch.float32) # 启用混合精度 scaler = torch.cuda.amp.GradScaler() with torch.cuda.amp.autocast(): outputs = model(inputs) loss = criterion(outputs, labels) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update() ``` --- ### 总结 - **默认情况**:ViT训练默认使用float32,平衡了稳定性和通用性。 - **优化场景**:可通过混合精度(float16/float32)提升效率,但需注意梯度管理和硬件兼容性。 - **建议**:在资源充足时优先使用float32;资源受限时尝试混合精度,并监控训练损失是否稳定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东华果汁哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值