TensorFlow/PyTorch实战:手把手教你构建猫狗图像分类器
175
0
0
0
前言
想不想亲手搭建一个能够区分猫和狗的图像分类器?本文将带你一步步使用Python中的TensorFlow或PyTorch框架,构建一个简单而有效的图像分类模型。我们将涵盖数据准备、模型选择、训练以及评估等关键步骤,让你从零开始,掌握图像分类的基本技能。
1. 数据准备
1.1 数据集获取
首先,你需要一个包含猫和狗图片的训练数据集。你可以从Kaggle的Dogs vs. Cats竞赛页面下载数据集。下载后,你会得到包含猫和狗图片的train.zip压缩包。
1.2 数据集组织
为了方便训练,我们需要将数据集组织成如下结构:
data/
train/
cats/
cat.0.jpg
cat.1.jpg
...
dogs/
dog.0.jpg
dog.1.jpg
...
validation/
cats/
cat.1000.jpg
cat.1001.jpg
...
dogs/
dog.1000.jpg
dog.1001.jpg
...
你可以编写一个Python脚本来完成数据集的组织工作。以下是一个示例脚本:
import os
import random
import shutil
def create_dir_if_not_exists(path):
if not os.path.exists(path):
os.makedirs(path)
# 原始数据目录
original_dataset_dir = 'train'
# 目标数据目录
base_dir = 'data'
create_dir_if_not_exists(base_dir)
train_dir = os.path.join(base_dir, 'train')
create_dir_if_not_exists(train_dir)
validation_dir = os.path.join(base_dir, 'validation')
create_dir_if_not_exists(validation_dir)
train_cats_dir = os.path.join(train_dir, 'cats')
create_dir_if_not_exists(train_cats_dir)
train_dogs_dir = os.path.join(train_dir, 'dogs')
create_dir_if_not_exists(train_dogs_dir)
validation_cats_dir = os.path.join(validation_dir, 'cats')
create_dir_if_not_exists(validation_cats_dir)
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
create_dir_if_not_exists(validation_dogs_dir)
# 猫狗图片文件名列表
cats = [f for f in os.listdir(original_dataset_dir) if f.startswith('cat.')]
dogs = [f for f in os.listdir(original_dataset_dir) if f.startswith('dog.')]
# 划分训练集和验证集
train_ratio = 0.7
train_cats_num = int(len(cats) * train_ratio)
train_dogs_num = int(len(dogs) * train_ratio)
# 移动猫的图片到训练集和验证集
for i, cat in enumerate(cats):
if i < train_cats_num:
src = os.path.join(original_dataset_dir, cat)
dst = os.path.join(train_cats_dir, cat)
shutil.copyfile(src, dst)
else:
src = os.path.join(original_dataset_dir, cat)
dst = os.path.join(validation_cats_dir, cat)
shutil.copyfile(src, dst)
# 移动狗的图片到训练集和验证集
for i, dog in enumerate(dogs):
if i < train_dogs_num:
src = os.path.join(original_dataset_dir, dog)
dst = os.path.join(train_dogs_dir, dog)
shutil.copyfile(src, dst)
else:
src = os.path.join(original_dataset_dir, dog)
dst = os.path.join(validation_dogs_dir, dog)
shutil.copyfile(src, dst)
print('数据准备完成!')
1.3 数据预处理
图像数据需要进行预处理,以便更好地输入到模型中。常见的预处理操作包括:
- 缩放 (Scaling):将像素值缩放到0到1之间。
- 调整大小 (Resizing):将所有图像调整到统一的大小,例如224x224。
- 数据增强 (Data Augmentation):通过旋转、翻转、缩放等操作,增加训练数据的多样性,提高模型的泛化能力。
2. 模型选择
2.1 模型架构
对于图像分类任务,卷积神经网络 (Convolutional Neural Networks, CNNs) 是一个常用的选择。常见的CNN架构包括:
- VGG16/VGG19:经典的CNN架构,具有多个卷积层和池化层。
- ResNet50/ResNet101:引入了残差连接,可以训练更深的网络。
- MobileNetV2/MobileNetV3:轻量级的CNN架构,适合在移动设备上运行。
对于猫狗分类这个简单任务,我们可以选择一个相对简单的模型,例如使用几个卷积层和池化层组成的自定义模型,或者使用预训练的MobileNetV2模型。
2.2 TensorFlow实现
以下是使用TensorFlow构建一个简单CNN模型的示例代码:
import tensorflow as tf
from tensorflow.keras import layers, models
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(128, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(2, activation='softmax') # 2个类别:猫和狗
])
model.summary()
2.3 PyTorch实现
以下是使用PyTorch构建一个简单CNN模型的示例代码:
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 32, 3)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(32, 64, 3)
self.conv3 = nn.Conv2d(64, 128, 3)
self.fc1 = nn.Linear(128 * 26 * 26, 128)
self.fc2 = nn.Linear(128, 2)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = self.pool(F.relu(self.conv3(x)))
x = torch.flatten(x, 1) # flatten all dimensions except batch
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
model = Net()
print(model)
3. 模型训练
3.1 准备训练数据
在训练模型之前,需要将图像数据加载到内存中,并进行必要的预处理。TensorFlow和PyTorch都提供了方便的数据加载和预处理工具。
- TensorFlow: 使用
ImageDataGenerator可以方便地进行数据增强和加载。 - PyTorch: 使用
DataLoader和Dataset类可以自定义数据加载和预处理流程。
3.2 TensorFlow训练代码
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# 数据增强
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
validation_datagen = ImageDataGenerator(rescale=1./255)
# 数据加载
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=(224, 224),
batch_size=32,
class_mode='categorical')
validation_generator = validation_datagen.flow_from_directory(
validation_dir,
target_size=(224, 224),
batch_size=32,
class_mode='categorical')
# 编译模型
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
# 训练模型
history = model.fit(
train_generator,
steps_per_epoch=train_generator.samples // train_generator.batch_size,
epochs=10,
validation_data=validation_generator,
validation_steps=validation_generator.samples // validation_generator.batch_size)
3.3 PyTorch训练代码
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# 数据预处理
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
# 加载数据集
train_dataset = datasets.ImageFolder(root=train_dir, transform=transform)
validation_dataset = datasets.ImageFolder(root=validation_dir, transform=transform)
# 创建数据加载器
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
validation_loader = DataLoader(validation_dataset, batch_size=32, shuffle=False)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练循环
epochs = 10
for epoch in range(epochs):
running_loss = 0.0
for i, data in enumerate(train_loader, 0):
inputs, labels = data
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 + 1}, {i + 1:5d}] loss: {running_loss / 100:.3f}')
running_loss = 0.0
print('Finished Training')
4. 模型评估
训练完成后,需要评估模型在验证集上的性能。常用的评估指标包括:
- 准确率 (Accuracy):分类正确的样本比例。
- 精确率 (Precision):预测为正例的样本中,实际为正例的比例。
- 召回率 (Recall):实际为正例的样本中,被正确预测为正例的比例。
- F1值 (F1-score):精确率和召回率的调和平均值。
4.1 TensorFlow评估代码
loss, accuracy = model.evaluate(validation_generator,
steps=validation_generator.samples // validation_generator.batch_size)
print('Validation accuracy:', accuracy)
4.2 PyTorch评估代码
correct = 0
total = 0
with torch.no_grad():
for data in validation_loader:
images, labels = data
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the validation images: {100 * correct // total} %')
总结
本文详细介绍了如何使用TensorFlow或PyTorch构建一个简单的猫狗图像分类器。你学会了如何准备数据、选择模型、训练模型以及评估模型。希望本文能帮助你入门图像分类,并为后续更复杂的任务打下基础。 动手实践才是最好的学习方式,快去尝试构建你自己的图像分类器吧!