WEBKT

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: 使用 DataLoaderDataset 类可以自定义数据加载和预处理流程。

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构建一个简单的猫狗图像分类器。你学会了如何准备数据、选择模型、训练模型以及评估模型。希望本文能帮助你入门图像分类,并为后续更复杂的任务打下基础。 动手实践才是最好的学习方式,快去尝试构建你自己的图像分类器吧!

AI探索者 图像分类TensorFlowPyTorch

评论点评