vggnet训练自己数据集
时间: 2025-01-08 09:20:36 浏览: 3
### 使用 VGGNet 训练自定义数据集
#### 准备环境和加载库
为了使用 VGGNet 模型来训练自定义的数据集,在 Python 中可以利用 PyTorch 或 TensorFlow 库。这里先介绍基于 PyTorch 的实现方法。
安装必要的包之后,导入所需的模块:
```python
import torch
from torchvision import models, transforms
from torch.utils.data import DataLoader, Dataset
import os
from PIL import Image
```
#### 定义自定义数据集类
创建继承 `torch.utils.data.Dataset` 类的新类以适应特定需求的数据集结构。这通常涉及重写两个主要的方法:`__len__()` 和 `__getitem__()`.
```python
class CustomDataset(Dataset):
def __init__(self, root_dir, transform=None):
self.root_dir = root_dir
self.transform = transform
self.classes = sorted(os.listdir(root_dir))
self.class_to_idx = {cls_name: i for i, cls_name in enumerate(self.classes)}
self.imgs = []
for class_name in self.classes:
class_path = os.path.join(root_dir, class_name)
for img_file in os.listdir(class_path):
self.imgs.append((os.path.join(class_path, img_file), self.class_to_idx[class_name]))
def __len__(self):
return len(self.imgs)
def __getitem__(self, idx):
img_path, label = self.imgs[idx]
image = Image.open(img_path).convert('RGB')
if self.transform is not None:
image = self.transform(image)
return image, label
```
#### 数据预处理与增强
应用适当的数据转换操作对于提高模型性能至关重要。这些变换可能包括调整大小、裁剪以及颜色抖动等随机变化[^1]。
```python
data_transforms = {
'train': transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
}
```
#### 加载并准备数据
实例化之前定义好的自定义数据集对象,并通过 `DataLoader` 创建迭代器用于后续训练过程中的批量读取。
```python
image_datasets = {x: CustomDataset(root_dir=f'data/{x}', transform=data_transforms[x]) for x in ['train', 'val']}
dataloaders = {x: DataLoader(image_datasets[x], batch_size=4, shuffle=True, num_workers=4) for x in ['train', 'val']}
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}
class_names = image_datasets['train'].classes
```
#### 初始化 VGGNet 并修改分类层
下载预训练权重版本的 VGGNet 模型,并根据实际类别数量更改最后一层全连接层的输出维度。
```python
model_ft = models.vgg16(pretrained=True)
num_ftrs = model_ft.classifier[6].in_features
model_ft.classifier[6] = torch.nn.Linear(num_ftrs, len(class_names))
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model_ft = model_ft.to(device)
```
#### 设置优化器和损失函数
选择合适的优化算法(如 SGD),设置初始学习率和其他超参数;同时指定交叉熵作为多分类任务下的目标函数。
```python
criterion = torch.nn.CrossEntropyLoss()
optimizer_ft = torch.optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)
exp_lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)
```
#### 开始训练循环
编写一个简单的训练脚本来执行多次前向传播、反向传播更新网络权值的过程直到满足停止条件为止。
```python
def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
best_acc = 0.0
for epoch in range(num_epochs):
print(f'Epoch {epoch}/{num_epochs - 1}')
print('-' * 10)
# Each epoch has a training and validation phase
for phase in ['train', 'val']:
if phase == 'train':
model.train()
else:
model.eval()
running_loss = 0.0
running_corrects = 0
for inputs, labels in dataloaders[phase]:
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad()
with torch.set_grad_enabled(phase == 'train'):
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
if phase == 'train':
loss.backward()
optimizer.step()
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data)
if phase == 'train':
scheduler.step()
epoch_loss = running_loss / dataset_sizes[phase]
epoch_acc = running_corrects.double() / dataset_sizes[phase]
print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')
if phase == 'val' and epoch_acc > best_acc:
best_acc = epoch_acc
print(f'Best val Acc: {best_acc:4f}')
return model
```
调用上述编写的 `train_model` 方法即可启动整个流程。
阅读全文