一、引言
在计算机视觉范畴内,图像分类属于基础且关键的任务。其应用场景极为宽泛,从医疗影像的病症诊断到自动驾驶里的交通标志识别,均依赖图像分类技术。本文将详尽阐述怎样运用卷积神经网络(Convolutional Neural Network, CNN)对蝴蝶图像实施分类。我们会逐步呈现从数据筹备到模型训练、评估的整个流程,借助Python以及相关深度学习库达成这一分类任务。
二、环境准备
在开启项目之前,我们需安装一些必要的库。这些库涉及数据处理、模型构建以及可视化等多个层面。以下是所需的主要库及其功用:
os
用于处理文件和目录路径。
numpy
用于开展高效的数值计算。
pandas
用于数据处理与分析,尤其适用于处理CSV文件。
matplotlib
用于数据可视化,展示训练过程与图像样本。
sklearn
提供机器学习相关工具,如数据集划分。
tensorflow.keras
用于构建和训练深度学习模型。
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
三、数据准备与检查
3.1 数据路径设置
我们需要指定数据集的根目录、图像文件夹以及标签CSV文件的路径。在该项目中,训练和验证图像均存于同一个文件夹中。
dataset_root = r'C:\Users\31146\Desktop\dataset-shenjing\dataset'
image_dir = os.path.join(dataset_root, 'train')
training_csv_path = os.path.join(dataset_root, 'Training_set.csv')
3.2 读取与检查数据
运用
pandas
读取CSV标签文件,并检查数据的基本信息,涵盖前几行、样本数量以及类别数量。同时,为确保数据分布的均衡性,我们采用分层抽样的方法。
df = pd.read_csv(training_csv_path)
print("训练集标签前5行:")
print(df.head())
print(f"\n总样本数:{len(df)},类别数:{df['label'].nunique()}")
3.3 数据集划分
将数据按照8:2的比例划分为训练集和验证集,并利用
random_state=42
保障结果的可复现性。
train_df, val_df = train_test_split(
df, test_size=0.2, random_state=42, stratify=df['label']
)
print(f"\n训练集大小:{len(train_df)},验证集大小:{len(val_df)}")
四、数据预处理与增强
4.1 数据增强设置
为了提升模型的泛化能力,我们对训练集进行数据增强操作,包括旋转、平移、剪切、缩放和水平翻转等。而验证集只进行归一化处理。
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'
)
val_datagen = ImageDataGenerator(rescale=1. / 255)
4.2 创建数据生成器
使用
ImageDataGenerator
flow_from_dataframe
创建训练集和验证集的数据生成器,统一将图像调整为150x150的分辨率。
batch_size = 32
target_size = (150, 150)
class_mode = 'categorical'
train_generator = train_datagen.flow_from_dataframe(
train_df, directory=image_dir, x_col='filename', y_col='label',
target_size=target_size, batch_size=batch_size, class_mode=class_mode
)
val_generator = val_datagen.flow_from_dataframe(
val_df, directory=image_dir, x_col='filename', y_col='label',
target_size=target_size, batch_size=batch_size, class_mode=class_mode
)
print(f"\n训练集样本数:{train_generator.n},验证集样本数:{val_generator.n}")
五、数据可视化
为了检查数据增强的效果,我们随机抽取10张训练集样本,并显示图像及其类别标签。
def plot_sample_images(generator, title="样本示例", num_images=10):
images, labels = next(generator)
class_names = list(generator.class_indices.keys())
plt.figure(figsize=(15, 10))
plt.suptitle(title, fontsize=16)
for i in range(min(num_images, len(images))):
plt.subplot(2, 5, i + 1)
plt.imshow(images[i])
class_idx = np.argmax(labels[i])
plt.title(f" 类别:{class_names[class_idx]}", fontsize=12)
plt.axis('off')
plt.tight_layout()
plt.show()
plot_sample_images(train_generator, "训练集样本")
六、构建CNN模型
6.1 网络结构
我们构建一个简单的CNN模型,包含3层卷积层、最大池化层、展平层、全连接层和输出层。
model = Sequential([
Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)),
MaxPooling2D((2, 2)),
Conv2D(64, (3, 3), activation='relu'),
MaxPooling2D((2, 2)),
Conv2D(128, (3, 3), activation='relu'),
MaxPooling2D((2, 2)),
Flatten(),
Dense(128, activation='relu'),
Dropout(0.5),
Dense(len(train_generator.class_indices), activation='softmax')
])
6.2 编译配置
使用Adam优化器(学习率为0.001)和交叉熵损失函数编译模型。
model.compile(optimizer=Adam(0.001), loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
七、模型训练
7.1 训练参数设置
设置批量大小为32,最大轮次为40,并使用早停机制(监控验证集损失,耐心值为5),同时保存最佳模型。
callbacks = [
EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True),
ModelCheckpoint('best_model.h5', save_best_only=True)
]
7.2 模型训练
使用数据生成器对模型进行训练,并记录训练和验证的准确率和损失。
history = model.fit(
train_generator,
steps_per_epoch=train_generator.n // batch_size,
epochs=40,
validation_data=val_generator,
validation_steps=val_generator.n // batch_size,
callbacks=callbacks
)
八、训练过程可视化
绘制训练集和验证集的准确率和损失曲线,通过曲线的走势分析模型是否存在过拟合或欠拟合的情况。
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.plot(history.history['accuracy'], label='训练集准确率')
plt.plot(history.history['val_accuracy'], label='验证集准确率')
plt.title(' 准确率变化')
plt.xlabel(' 轮数')
plt.ylabel(' 准确率')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(history.history['loss'], label='训练集损失')
plt.plot(history.history['val_loss'], label='验证集损失')
plt.title(' 损失变化')
plt.xlabel(' 轮数')
plt.ylabel(' 损失值')
plt.legend()
plt.show()
九、模型验证与预测
从验证集中随机选择一张图像,加载最佳模型进行预测,并显示预测结果(类别名称和置信度),直观评估模型的性能。
def predict_butterfly(image_path):
from tensorflow.keras.preprocessing import image
img = image.load_img(image_path, target_size=target_size)
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0) / 255.0
prediction = model.predict(img_array)
class_idx = np.argmax(prediction)
class_name = list(train_generator.class_indices.keys())[class_idx]
confidence = np.max(prediction)
plt.imshow(img)
plt.title(f" 预测:{class_name}\n置信度:{confidence:.2f}", fontsize=14)
plt.axis('off')
plt.show()
return class_name, confidence
if len(val_df) > 0:
sample_filename = val_df.iloc[0]['filename']
sample_image_path = os.path.join(image_dir, sample_filename)
print("\n预测示例:")
predict_butterfly(sample_image_path)
十、总结
通过以上步骤,我们完成了一个完整的图像分类项目,从数据准备到模型训练和评估。在这个过程中,数据增强和早停机制等技术的应用有助于提升模型的性能和泛化能力。同时,通过可视化训练过程和预测结果,我们可以更直观地了解模型的表现。希望本文能为你在图像分类领域的学习和实践提供一些参考。