从零开始使用chinesefoodnet数据集:数据预处理与模型训练实战指南

1次阅读
没有评论

共计 3103 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

数据集背景介绍

ChineseFoodNet 是一个包含 108 种中式菜品、总计 18.5 万张图像的数据集。它最早由中科院在 2018 年发布,主要用于食品识别和分类研究。数据集的特点是菜品类别覆盖广(从宫保鸡丁到阳春面),但存在以下挑战:

从零开始使用 chinesefoodnet 数据集:数据预处理与模型训练实战指南

  • 图像尺寸不统一(从 300×400 到 2000×3000 不等)
  • 光照条件差异大(部分拍摄于餐厅,部分来自网络)
  • 标注文件采用 JSON 格式,需要特殊解析

典型应用场景包括:

  • 智能餐厅的自动结账系统
  • 健康饮食 APP 的热量估算
  • 外卖平台的图像搜索功能

数据预处理实战

1. 环境准备

首先安装必要依赖(建议使用 conda 环境):

conda create -n food python=3.8
conda install pytorch==1.10 torchvision -c pytorch
pip install opencv-python pandas tqdm

2. 数据加载

数据集解压后通常包含以下结构:

dataset_root/
├── annotations/
│   ├── train.json
│   └── test.json
└── images/
    ├── 000001.jpg
    ├── 000002.jpg
    ...

使用以下代码加载标注信息:

import json
import pandas as pd

with open('annotations/train.json') as f:
    train_data = json.load(f)

# 转换为 DataFrame 方便处理
train_df = pd.DataFrame({'image_path': [f"images/{x['image_id']}.jpg" for x in train_data],
    'label': [x['category_id'] for x in train_data]
})

3. 图像预处理

关键预处理步骤包括:

  1. 统一缩放到 256×256 尺寸
  2. 随机水平翻转增强
  3. 归一化到 [0,1] 范围

PyTorch 实现示例:

from torchvision import transforms

# 定义训练集变换
train_transform = transforms.Compose([transforms.Resize(256),  # 先调整短边为 256
    transforms.CenterCrop(224),  # 中心裁剪
    transforms.RandomHorizontalFlip(),  # 数据增强
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], 
                         std=[0.229, 0.224, 0.225])
])

# 验证集只需要基础变换
val_transform = transforms.Compose([transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], 
                         std=[0.229, 0.224, 0.225])
])

模型训练示例

基础 CNN 模型

以下是一个适合新手的简单架构:

import torch.nn as nn
import torch.nn.functional as F

class SimpleCNN(nn.Module):
    def __init__(self, num_classes=108):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.fc1 = nn.Linear(64 * 56 * 56, 512)  # 224/2/2=56
        self.fc2 = nn.Linear(512, num_classes)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 64 * 56 * 56)  # 展平
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

训练循环

完整训练流程示例:

from torch.utils.data import DataLoader

model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for epoch in range(10):
    model.train()
    for images, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    # 验证阶段
    model.eval()
    correct = 0
    with torch.no_grad():
        for images, labels in val_loader:
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1)
            correct += (predicted == labels).sum().item()

    print(f'Epoch {epoch}: Acc {correct/total:.2f}')

性能优化技巧

批量大小选择

  • 显存充足时:使用较大 batch(如 64/128)加速训练
  • 显存有限时:尝试梯度累积(accumulate gradients)
# 梯度累积示例
accum_steps = 4
for i, (images, labels) in enumerate(train_loader):
    outputs = model(images)
    loss = criterion(outputs, labels)
    loss = loss / accum_steps  # 平均损失
    loss.backward()

    if (i+1) % accum_steps == 0:
        optimizer.step()
        optimizer.zero_grad()

学习率调整

推荐使用余弦退火策略:

from torch.optim.lr_scheduler import CosineAnnealingLR

scheduler = CosineAnnealingLR(optimizer, T_max=10)  # 10 个 epoch 周期

避坑指南

  1. 内存溢出问题:
  2. 现象:训练时突然崩溃
  3. 解决:减小 batch_size 或使用更小的图像尺寸

  4. 标签错位:

  5. 现象:准确率始终接近 0
  6. 检查:确认 DataLoader 返回的标签与图像对应

  7. 梯度爆炸:

  8. 现象:loss 变为 NaN
  9. 解决:添加梯度裁剪torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)

  10. 数据泄漏:

  11. 现象:验证集准确率异常高
  12. 检查:确保训练集和验证集没有重叠样本

  13. 预处理不一致:

  14. 现象:部署时效果下降
  15. 解决:训练和推理使用完全相同的 transform

延伸学习

  • 进阶模型:尝试 ResNet18 等预训练模型
  • 更复杂的数据增强:MixUp、CutMix
  • 类别不平衡处理:Focal Loss
  • 在线学习:使用少量新菜品样本微调模型

完整代码示例已上传 GitHub 仓库(假设链接),包含更多注释和可视化工具。建议从简单模型开始,逐步增加复杂度,祝各位训练顺利!

正文完
 0
评论(没有评论)