共计 2789 个字符,预计需要花费 7 分钟才能阅读完成。
数据集背景介绍
chinesefoodnet 是一个专门针对中国菜品的图像分类数据集,包含超过 10 万张高质量食物图片,涵盖 200 多种常见中式菜品。数据集结构通常如下:

chinesefoodnet/
├── train/
│ ├── 宫保鸡丁 /
│ │ ├── 001.jpg
│ │ └── ...
│ └── ... 其他菜品
└── test/
├── 鱼香肉丝 /
│ ├── 001.jpg
│ └── ...
└── ... 其他菜品
- 每张图片尺寸不一,常见为 500×500 到 2000×2000 像素
- 标注信息存储在 JSON 文件中,包含菜品名称和边界框信息
- 典型应用包括:智能点餐系统、营养分析、美食推荐等
数据预处理实战
- 安装依赖库
pip install torch torchvision pillow pandas
- 基础数据加载
from torchvision import datasets, transforms
# 定义基础转换
transform = transforms.Compose([transforms.Resize(256), # 统一尺寸
transforms.CenterCrop(224), # 中心裁剪
transforms.ToTensor(), # 转为 Tensor
transforms.Normalize(mean=[0.485, 0.456, 0.406], # ImageNet 均值
std=[0.229, 0.224, 0.225]) # ImageNet 标准差
])
# 加载数据集
dataset = datasets.ImageFolder('chinesefoodnet/train', transform=transform)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=32, shuffle=True)
- 数据增强(训练时使用)
train_transform = transforms.Compose([transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
模型训练示例
- 简单 CNN 模型实现
import torch.nn as nn
import torch.nn.functional as F
class SimpleFoodCNN(nn.Module):
def __init__(self, num_classes=200):
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) # 输入尺寸需要根据实际情况调整
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 = torch.flatten(x, 1)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
- 完整训练循环
model = SimpleFoodCNN().cuda()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
for epoch in range(10):
running_loss = 0.0
for i, (inputs, labels) in enumerate(dataloader):
inputs, labels = inputs.cuda(), labels.cuda()
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99:
print(f'Epoch {epoch+1}, Batch {i+1}: loss {running_loss/100:.3f}')
running_loss = 0.0
性能优化技巧
- 批量大小选择
- 显存充足时(如 16GB+):尝试 128-256 的 batch size
- 普通显卡(如 8GB):32-64 更安全
-
可配合梯度累积技术模拟更大 batch
-
学习率调整策略
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
# 每个 epoch 后调用 scheduler.step()
- 混合精度训练(需支持 FP16 的 GPU)
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()
避坑指南
- 内存溢出问题
- 症状:训练时突然崩溃
-
解法:减小 batch size 或图像尺寸
-
类别不平衡
- 症状:某些菜品准确率极低
-
解法:使用加权采样或 focal loss
-
过拟合
- 症状:训练准确高但测试差
-
解法:增加 Dropout 层或数据增强
-
学习率不当
- 症状:loss 不下降或剧烈波动
-
解法:尝试 1e- 3 到 1e- 5 范围
-
预处理不一致
- 症状:部署时性能下降
- 解法:确保训练和推理使用相同 transform
延伸学习建议
- 尝试更复杂模型:ResNet、EfficientNet 等预训练模型
- 探索多标签分类:一道菜可能属于多个类别
- 加入目标检测:使用边界框信息实现菜品定位
- 迁移学习:用 Food-101 等大型食物数据集预训练
- 部署优化:转换为 ONNX 或 TensorRT 格式加速推理
结语
通过本教程,你应该已经掌握了 chinesefoodnet 数据集的基本使用方法。实际应用中可能会遇到更多挑战,但核心处理流程是相通的。建议先从简单模型开始,逐步迭代优化,同时注意记录每次实验的参数和结果,这对理解模型行为非常有帮助。
正文完
