ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Keras搭建CNN实现猫狗图像分类:从预处理到调参实战记录

Keras搭建CNN实现猫狗图像分类:从预处理到调参实战记录 简介基于Keras的猫狗分类识别实验报告22页是一份面向机器学习课程期末大作业的高分原创素材围绕Kaggle Dogs vs. Cats数据集给出完整的二分类识别方案适合计算机专业学生完成图像分类实验或期末报告时参考。压缩包内仅有1个docx文档大小5.16MB文档按摘要、引言、主体内容、实验与结果分析、结论、参考文献六部分组织结构规范清晰。内容覆盖CNN原理、AlexNet网络结构、损失函数评估、数据预处理与算法分析并附有算法流程图、运行结果截图和核心代码其中针对标签异常图像使用预训练模型结合微调top参数进行排查体现了较完整的调优思路。该报告在CSDN已有7899人学习可帮助读者快速搭建同类猫狗识别实验写出有深度、图文并茂的期末报告。1. 实验选题与整体设计思路这个实验应该算是我大学期间印象最深的一份大作业之一——用Keras搭建卷积神经网络完成猫狗图片的二分类识别。当年选这个题的时候纯粹是因为觉得猫狗分类听起来比手写数字识别酷多了结果真正动手做起来才发现这背后涉及的东西远不止搭一个网络那么简单。从数据集下载、图像预处理、模型构建到训练调参、评估可视化一套完整的深度学习项目流程下来基本把机器学习课程的核心知识点全过了一遍。先说说为什么这个选题适合作为大作业。猫狗分类本质上是一个图像二分类问题数据集公开好获取任务直观易懂而且准确率能做到90%以上也不太难属于看着高级、做着可控的典型项目。同时它又足够有代表性——原始图片尺寸不一致、数据量有限、背景干扰多、类别间相似度高这些问题恰恰是实际工程中最常遇到的比MNIST那种数据集已经帮你洗干净的任务有价值得多。1.1 核心需求拆解我给自己定了几个明确的实验目标这也是我建议你们在做之前先想清楚的问题通过Keras搭建一个CNN模型完成猫狗图片的二分类测试集准确率目标80%以上熟悉图像数据的基本预处理流程包括图片读取、尺寸统一、像素归一化掌握数据增强Data Augmentation的原理与实战用法理解它为什么能缓解过拟合学会训练过程的监控与可视化能从loss曲线和accuracy曲线中判断模型状态实现单张图片的预测并可视化卷积层的特征图直观理解CNN在看什么1.2 技术选型为什么是Keras当时其实纠结过是用TensorFlow、PyTorch还是Keras。最终选Keras原因很简单在TensorFlow 2.x还没那么成熟的年代Keras的高层API封装得极其友好几行代码就能搭建并训练一个卷积神经网络。它把数据加载、模型构建、训练循环、评估预测全都做成了模块化接口对初学者来说能让你把注意力集中在理解网络结构和训练逻辑上而不是被底层张量运算劝退。后来课程里还要求对比传统机器学习方法我用SVMHOG特征做过一组对照实验结果在相同数据集上SVM大概能到75%左右而CNN轻松上90%。这个对比本身就很有说服力——深度学习在图像任务上的优势是碾压性的但代价是需要GPU、更多数据和更长训练时间。这份报告里我把两个方法的原理差异也写了这会让你的大作业显得更有思考深度。2. 数据集准备与图像预处理2.1 数据集来源与目录结构数据集用的是Kaggle经典的Dogs vs Cats原始训练集有25000张猫狗图片测试集12500张。完整下载接近1GB如果你只是为了交大作业其实不用全量——我建议从训练集里按比例抽一部分比如猫狗各6000张左右训练集8000张、验证集2000张、测试集2000张比例大概8:1:1这样训练速度和效果都比较平衡。数据集的目录结构建议这样组织Keras的ImageDataGenerator的flow_from_directory方法就是按文件夹名来自动标注类别的data/ ├── train/ │ ├── cats/ # 猫图文件名随意如 cat.001.jpg │ └── dogs/ # 狗图如 dog.001.jpg ├── validation/ │ ├── cats/ │ └── dogs/ └── test/ ├── cats/ └── dogs/2.2 图像预处理的关键细节拿到图片后首要问题是尺寸不统一有的图是600x480有的是1024x768甚至还有长宽比完全不同的。CNN要求输入张量形状固定所以必须统一resize。我选的是150x150x3这是Keras官方教程里用的尺寸不算大训练速度快对猫狗识别也足够了。第二个关键点是像素值归一化原始图片的像素范围是0到255直接塞给网络会让梯度更新不稳定收敛慢。常见做法是除以255缩放到0到1区间。训练集、验证集、测试集都要做同样的归一化这是最容易漏的细节。第三个点是图像增强Data Augmentation这是防止过拟合最有效的手段之一。Keras里实现非常简单from keras.preprocessing.image import ImageDataGenerator # 训练数据生成器带数据增强 train_datagen ImageDataGenerator( rescale1./255, # 像素归一化 rotation_range40, # 随机旋转 0~40度 width_shift_range0.2, # 水平平移 20% height_shift_range0.2, # 垂直平移 20% shear_range0.2, # 错切变换 zoom_range0.2, # 随机缩放 horizontal_flipTrue, # 水平翻转 fill_modenearest # 填充模式 ) # 验证集、测试集只归一化不增强 test_datagen ImageDataGenerator(rescale1./255)这里有个重要的原理需要理解透彻数据增强不是在收集更多图片而是在训练过程中对每张原始图片做随机变换相当于每轮epoch模型看到的都是新的图片。比如一张猫图翻转一下、旋转15度、稍微放大一点语义还是猫但对模型来说就是不同的输入。这样能有效扩大训练样本的多样性让模型学到更泛化的特征而不是死记硬背某张图的细节。注意数据增强只应该用在训练集验证集和测试集不能做增强。否则验证集的指标就不客观了——你评估的模型和实际部署时的输入分布不一致结果没有参考意义。3. 模型构建与训练过程3.1 卷积神经网络结构设计模型结构我参考了VGG16的设计思路但因为数据集相对简单没有直接用预训练模型而是自己搭了一个小型的CNN。层数不用太多三层卷积就够用了参数规模控制在可训练范围内。from keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout from keras.optimizers import Adam model Sequential([ # 第一层卷积32个3x3卷积核输入150x150x3 Conv2D(32, (3, 3), activationrelu, input_shape(150, 150, 3)), MaxPooling2D(2, 2), # 第二层卷积64个3x3卷积核 Conv2D(64, (3, 3), activationrelu), MaxPooling2D(2, 2), # 第三层卷积128个3x3卷积核 Conv2D(128, (3, 3), activationrelu), MaxPooling2D(2, 2), # 展平后接全连接层 Flatten(), Dropout(0.5), Dense(512, activationrelu), Dense(1, activationsigmoid) # 二分类用sigmoid输出概率 ]) model.compile(optimizerAdam(learning_rate1e-4), lossbinary_crossentropy, metrics[accuracy])说几个容易被忽略的点。一是全连接层数量别太大513x512的参数已经不少了再大容易过拟合。二是Dropout加在Flatten和Dense之间比例为0.5这是经验值——训练时随机丢弃一半神经元测试时全部使用但权重减半相当于训练了很多个子网络的集成能显著缓解过拟合。激活函数选ReLU而不是sigmoid/tanh主要是因为ReLU能有效缓解梯度消失问题计算也快。最后一层输出必须用sigmoid因为二分类输出应该是0到1之间的概率值配合binary_crossentropy损失函数使用。如果是多分类这里就得换成softmax加categorical_crossentropy。3.2 训练过程与损失曲线分析训练参数我也给出自己的配置可以直接参考history model.fit( train_generator, steps_per_epoch100, # 每轮迭代次数 epochs50, # 训练轮数 validation_dataval_generator, validation_steps50, # 验证迭代次数 verbose1 )这里有个细节值得展开说steps_per_epoch等于训练集样本数除以batch_size。假设训练集有8000张图片batch_size设为32 那么一个epoch需要的迭代次数 8000 / 32 250次。 但在flow_from_directory里steps_per_epoch是一个手动指定的值 如果用100意味着每个epoch只看了 100 * 32 3200张图 不是完完整整的把8000张都过一遍。我当时训练了50个epoch每轮大概二十多秒GTX 1060总共用了一刻钟左右。如果是用CPU训练差不多要一个小时以上这个时间成本你们得提前预估好。训练过程中我把history对象直接保存成了pickle文件后面画图直接用不用再重新训练一次这个习惯建议大家养成。训练完成后绘制loss曲线和accuracy曲线是非常关键的诊断手段。正常收敛的曲线应该是训练loss和验证loss都下降然后趋于平缓。如果训练loss持续下降但验证loss先降后升那就是经典的过拟合信号说明模型开始死记训练集内容了。我跑的模型在约35个epoch后验证准确率稳定在90%上下训练准确率92%左右过拟合并不严重主要归功于数据增强和Dropout这两个操作。4. 预测评估与可视化4.1 测试集评估训练完成后在真正的测试集上做评估test_loss, test_acc model.evaluate(test_generator, steps50) print(fTest accuracy: {test_acc:.4f})我当时测试集准确率大约在89%这个成绩比预想的稍低一点主要原因是测试集里有一些非常规角度的图片、卡通图片和多只动物同框的情况即使是人眼判断也很吃力。为了更直观地展示效果我还做了分类报告和混淆矩阵from sklearn.metrics import confusion_matrix, classification_report y_pred model.predict(test_generator) y_pred_binary (y_pred 0.5).astype(int) print(confusion_matrix(y_true, y_pred_binary)) print(classification_report(y_true, y_pred_binary, target_names[cat, dog]))混淆矩阵能清楚看出模型是偏爱预测猫还是狗。我的实验里狗的召回率略高一点点猜测原因是训练集中的狗图背景通常更多样而猫图居家室内场景偏多特征不够多样。4.2 单张图片预测与可视化随机挑几张没有参与训练的新图做预测这一步能直观看到模型的表现。比如自己从网上下载或者手机拍的猫狗照片resize到150x150归一化喂给模型from keras.preprocessing import image import numpy as np def predict_image(img_path): img image.load_img(img_path, target_size(150, 150)) img_array image.img_to_array(img) img_array np.expand_dims(img_array, axis0) # 变batch维度 img_array / 255.0 pred model.predict(img_array) if pred[0][0] 0.5: print(f预测结果: 狗 (置信度: {pred[0][0]:.4f})) else: print(f预测结果: 猫 (置信度: {1 - pred[0][0]:.4f}))这里有个非常容易踩的坑原图是RGB三通道的读取后是(150,150,3)但Keras的模型输入要求是(batch_size, 150, 150, 3)所以必须用np.expand_dims在第一个维度上加一个批次维度。我第一次写的时候漏了这一步直接报维度错误查了半天才定位到。更高级的可视化是卷积层特征图。通过设置Keras的backend函数可以提取中间层的输出来看看模型到底提取了哪些特征from keras import backend as K layer_outputs [layer.output for layer in model.layers[:8]] activation_model Model(inputsmodel.input, outputslayer_outputs) activations activation_model.predict(img_array) # 第0层是第一个卷积层的输出 first_layer_activation activations[0] plt.matshow(first_layer_activation[0, :, :, 3], cmapviridis)打印出来你会发现浅层卷积核学到的是边缘、纹理、颜色等低级特征比如猫的轮廓、毛发的方向深层卷积核则能捕捉到眼睛、耳朵、鼻子等语义特征。这个可视化放到报告里导师看了会觉得你是真的理解CNN了而不是只会调用model.fit。5. 常见问题与排查技巧实录这部分是我认为整篇报告里价值最高的内容。想把实验做成一个高分大作业需要的是把各种坑都跳过。5.1 Keras环境搭建问题环境搭建真的会让很多人卡住。当年我用的还是TensorFlow 1.x配Keras 2.x现在环境已经简单多了直接安装TensorFlow 2.x就自带Keras模块。建议用conda创建独立环境Python版本3.7或3.8比较稳太高版本可能有兼容性问题。conda create -n keras_env python3.8 conda activate keras_env pip install tensorflow2.4.1 pip install matplotlib scikit-learn jupyter如果你是NVIDIA显卡能用GPU训练最好速度能快10倍以上。装GPU版的时候注意CUDA版本和cuDNN版本的匹配问题这是全网踩坑最多的环节。装完验证GPU是否可用import tensorflow as tf print(GPU Available: , tf.config.list_physical_devices(GPU))5.2 训练不收敛或loss为NaN这是我遇到过的比较惊心动魄的情况之一。迭代到某一步loss突然变成NaN所有的权重参数全部崩溃。排查后发现是学习率设置的太大导致梯度更新直接爆炸。解决办法是把learning_rate从默认的0.001降到1e-4或者用更稳健的Adam优化器。还有一种可能是数据里有损坏的图片文件或者不是标准的RGB图比如灰度图、有透明通道的PNG。ImageDataGenerator读图时遇到非预期格式会把像素值填充为极端值导致loss异常。解决方法是在数据预处理时统一转成RGB并做完整性校验。5.3 类别不平衡问题实战中最常见的陷阱就是类别不平衡比如训练集里猫7000张、狗1000张模型会倾向把所有图片都预测为猫因为这样准确率也有87%。Keras里可以通过class_weight参数来调整损失函数中类别的权重给少数类更高的权重让模型更重视这些样本。class_weight {0: 1.0, 1: 7.0} # 类别0是猫类别1是狗 model.fit(..., class_weightclass_weight)5.4 数据增强后验证准确率不升反降我试过把增强力度调得过大比如旋转角度设成90度结果模型反而变笨了。原因是猫狗照片不是你转90度它还看得出来是猫——竖构图的长条形猫转成横的语义就变了。合理的增强是模拟真实场景中的变化比如轻微旋转、平移、缩放、翻转而不是制造反常识的数据。建议rotation_range不要超过30zoom_range控制在0.2以内。5.5 训练时间过长怎么办如果你的机器没有GPU训练50个epoch可能要跑几个小时。几个优化思路降低图片尺寸从150x150降到128x128甚至96x96准确率损失不大但速度提升明显减少训练集数量每类2000张其实也够用减少epoch数到30配合early stopping自动在验证集不再提升时停止用预训练模型的迁移学习VGG16或者MobileNet几行代码就能把特征提取部分固定住只训练最后几层速度和准确率都有保障从我自己折腾这个项目的整体感受来说最大的收获不是模型准确率最后达到了多少而是完整地走通了一遍数据准备→建模→训练→评估→调优的流程。这个流程对之后做任何机器学习项目都是相通的。最后说一个实用小技巧实验过程中把每次调参的配置和对应的准确率记在一个表格里比如数据集大小、是否数据增强、学习率、网络深度、最终准确率。最后报告里放一张实验记录对照表导师一看就知道你是真动手做了实验的而不仅仅是跑了一遍官方示例代码这比任何漂亮的结论都更有说服力。本文还有配套的精品资源点击获取
返回列表