尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
T7周:咖啡豆识别
本文为365天深度学习训练营中的学习记录博客原作者K同学啊学习目的 要求自己搭建VGG-16网络框架调用官方的VGG-16网络框架 拔高可选验证集准确率达到100%使用PPT画出VGG-16算法框架图发论文需要这项技能 探索难度有点大在不影响准确率的前提下轻量化模型○ 目前VGG16的Total params是134,276,932一、 前期准备关于环境语言环境Python3.6编译器vsCode深度学习环境TensorFlow 2.6.21.数据导入import tensorflow as tf import os,PIL,pathlib import matplotlib.pyplot as plt import numpy as np from tensorflow import keras from tensorflow.keras import layers,modelsdata_dir C:/Users/hsq/Desktop/train/D7/ data_dir pathlib.Path(data_dir)image_count len(list(data_dir.glob(*/*.png))) print(图片总数为,image_count)注意图片后缀格式格式不对读出来的图片数量可能为0二、数据预处理1. 加载数据使用image_dataset_from_directory方法将磁盘中的数据加载到tf.data.Dataset中batch_size 32 img_height 224 img_width 224 关于image_dataset_from_directory()的详细介绍可以参考文章https://mtyjkh.blog.csdn.net/article/details/117018789 train_ds tf.keras.preprocessing.image_dataset_from_directory( data_dir, validation_split0.2, subsettraining, seed123, image_size(img_height, img_width), batch_sizebatch_size)代码运行结果 关于image_dataset_from_directory()的详细介绍可以参考文章https://mtyjkh.blog.csdn.net/article/details/117018789 val_ds tf.keras.preprocessing.image_dataset_from_directory( data_dir, validation_split0.2, subsetvalidation, seed123, image_size(img_height, img_width), batch_sizebatch_size)代码运行结果注意划分比例0.1、0.2、0.3训练集和验证集划分数量不同class_names train_ds.class_names print(class_names)代码运行结果本次为4分类任务2. 可视化数据plt.figure(figsize(10, 4)) # 图形的宽为10高为5 for images, labels in train_ds.take(1): for i in range(10): ax plt.subplot(2, 5, i 1) plt.imshow(images[i].numpy().astype(uint8)) plt.title(class_names[labels[i]]) plt.axis(off)代码运行结果3. 再次检查数据for image_batch, labels_batch in train_ds: print(image_batch.shape) print(labels_batch.shape) break代码运行结果Image_batch是形状的张量32,224,224,3。这是一批形状224x224x3的32张图片Label_batch是形状32的张量这些标签对应32张图片共4个标签4. 配置数据集shuffle()打乱数据prefetch()预取数据加速运行。cache()将数据集缓存到内存当中加速运行AUTOTUNE tf.data.AUTOTUNE train_ds train_ds.cache().shuffle(1000).prefetch(buffer_sizeAUTOTUNE) val_ds val_ds.cache().prefetch(buffer_sizeAUTOTUNE)normalization_layer layers.experimental.preprocessing.Rescaling(1./255) train_ds train_ds.map(lambda x, y: (normalization_layer(x), y)) val_ds val_ds.map(lambda x, y: (normalization_layer(x), y))image_batch, labels_batch next(iter(val_ds)) first_image image_batch[0] # 查看归一化后的数据 print(np.min(first_image), np.max(first_image))代码运行结果三、调用官方VGG-16from tensorflow.keras.applications.vgg16 import VGG16, preprocess_input from tensorflow.keras.preprocessing import image # 加载VGG16卷积部分冻结权重 base_model VGG16(weightsimagenet, include_topFalse, input_shape(224,224,3)) base_model.trainable True # 冻结预训练参数 for layer in base_model.layers: if layer.name.startswith(block5): layer.trainable True else: layer.trainable False # 构建自己的分类头 inputs tf.keras.Input(shape(224,224,3)) x preprocess_input(inputs) x base_model(x, trainingFalse) x tf.keras.layers.GlobalAveragePooling2D()(x) outputs tf.keras.layers.Dense(4, activationsoftmax)(x) # 4分类 model tf.keras.Model(inputs, outputs) model.summary()注意分类头标签数量修改代码运行结果四、训练模型1.设置动态学习率# 设置初始学习率 initial_learning_rate 1e-4 lr_schedule tf.keras.optimizers.schedules.ExponentialDecay( initial_learning_rate, decay_steps60, # 敲黑板这里是指 steps不是指epochs decay_rate0.96, # lr经过一次衰减就会变成 decay_rate*lr staircaseTrue) # 将指数衰减学习率送入优化器 optimizer tf.keras.optimizers.Adam(learning_ratelr_schedule) model.compile(optimizeroptimizer, losstf.keras.losses.CategoricalCrossentropy(from_logits True), metrics[accuracy])2.早停与保存最佳模型参数from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping epochs 100 # 保存最佳模型参数 checkpointer ModelCheckpoint(best_model.h5, monitorval_accuracy, verbose1, save_best_onlyTrue, save_weights_onlyTrue) # 设置早停 earlystopper EarlyStopping(monitorval_accuracy, min_delta0.001, patience20, verbose1)3. 模型训练history model.fit(train_ds, validation_dataval_ds, epochsepochs, callbacks[checkpointer, earlystopper])代码运行结果五、模型评估1. Loss与Accuracy图from datetime import datetime current_time datetime.now() # 获取当前时间 acc history.history[accuracy] val_acc history.history[val_accuracy] loss history.history[loss] val_loss history.history[val_loss] epochs_range range(len(loss)) plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, labelTraining Accuracy) plt.plot(epochs_range, val_acc, labelValidation Accuracy) plt.legend(loclower right) plt.title(Training and Validation Accuracy) plt.xlabel(current_time) # 打卡请带上时间戳否则代码截图无效 plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, labelTraining Loss) plt.plot(epochs_range, val_loss, labelValidation Loss) plt.legend(locupper right) plt.title(Training and Validation Loss) plt.show()代码运行结果验证集预测效果未达100%对模型进行解冻from tensorflow.keras.applications.vgg16 import VGG16, preprocess_input from tensorflow.keras.preprocessing import image # 加载VGG16卷积部分冻结权重 base_model VGG16(weightsimagenet, include_topFalse, input_shape(224,224,3)) base_model.trainable True # 冻结预训练参数 for layer in base_model.layers: if layer.name.startswith(block5): layer.trainable True else: layer.trainable False # 构建自己的分类头 inputs tf.keras.Input(shape(224,224,3)) x preprocess_input(inputs) x base_model(x, trainingFalse) x tf.keras.layers.GlobalAveragePooling2D()(x) outputs tf.keras.layers.Dense(17, activationsoftmax)(x) # 10分类 model tf.keras.Model(inputs, outputs) model.summary()代码运行结果仅提升至89%六、手动搭建VGG-16模型这是之前学习Pytorch时使用PPT制作的结构框架图from tensorflow.keras import layers, models, Input from tensorflow.keras.models import Model from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout def VGG16(nb_classes, input_shape): input_tensor Input(shapeinput_shape) # 1st block x Conv2D(64, (3,3), activationrelu, paddingsame,nameblock1_conv1)(input_tensor) x Conv2D(64, (3,3), activationrelu, paddingsame,nameblock1_conv2)(x) x MaxPooling2D((2,2), strides(2,2), name block1_pool)(x) # 2nd block x Conv2D(128, (3,3), activationrelu, paddingsame,nameblock2_conv1)(x) x Conv2D(128, (3,3), activationrelu, paddingsame,nameblock2_conv2)(x) x MaxPooling2D((2,2), strides(2,2), name block2_pool)(x) # 3rd block x Conv2D(256, (3,3), activationrelu, paddingsame,nameblock3_conv1)(x) x Conv2D(256, (3,3), activationrelu, paddingsame,nameblock3_conv2)(x) x Conv2D(256, (3,3), activationrelu, paddingsame,nameblock3_conv3)(x) x MaxPooling2D((2,2), strides(2,2), name block3_pool)(x) # 4th block x Conv2D(512, (3,3), activationrelu, paddingsame,nameblock4_conv1)(x) x Conv2D(512, (3,3), activationrelu, paddingsame,nameblock4_conv2)(x) x Conv2D(512, (3,3), activationrelu, paddingsame,nameblock4_conv3)(x) x MaxPooling2D((2,2), strides(2,2), name block4_pool)(x) # 5th block x Conv2D(512, (3,3), activationrelu, paddingsame,nameblock5_conv1)(x) x Conv2D(512, (3,3), activationrelu, paddingsame,nameblock5_conv2)(x) x Conv2D(512, (3,3), activationrelu, paddingsame,nameblock5_conv3)(x) x MaxPooling2D((2,2), strides(2,2), name block5_pool)(x) # full connection x Flatten()(x) x Dense(4096, activationrelu, namefc1)(x) x Dense(4096, activationrelu, namefc2)(x) output_tensor Dense(nb_classes, activationsoftmax, namepredictions)(x) model Model(input_tensor, output_tensor) return model modelVGG16(len(class_names), (img_width, img_height, 3)) model.summary()代码运行结果手动搭建模型验证集准确率达99%五、轻量化模型1.替换全连接层为全局平均池化GAP这是VGG-16轻量化最应该做的一步。VGG-16的3个全连接层FC占了整个模型约 90% 的参数约1.2亿。做法移除最后的 Flatten FC(4096) FC(4096) FC(1000)改为 GlobalAveragePooling2D() 直接接 FC(1000)。效果参数量瞬间从 1.38亿 降至 ~1500万。精度影响由于GAP相当于强制让每个特征图对应一个类别不仅不掉点反而能提升泛化能力防止全连接层过拟合。在ImageNet上原版VGG-16 Top-1准确率约71.5%改为GAP后约71.2% 仅降0.3%但体积缩小十倍。2.通道剪枝Channel Pruning—— 针对卷积层移除3个FC后剩下的2000万参数主要来自卷积层。VGG-16的通道数64→128→256→512存在大量冗余。做法在训练后计算每个卷积核的 L1/L2范数权重绝对值之和剪掉贡献最小范数最低的20%~30%通道。然后在小学习率下微调Fine-tune3~5个epoch。效果FLOPs计算量减少约 30%~40%。精度影响微调后精度通常能 恢复到原模型的98%~99%即Top-1下降约0.5%~1%。3.SVD 矩阵 分解 —— 专门针对全连接层如果你坚持保留FC如果你不愿用GAP仍想保留FC层可以用 SVD奇异值分解 对 FC(4096) 的权重矩阵进行低秩近似。做法将 4096 x 25088 的巨型矩阵拆解为两个小矩阵相乘中间插入一个低秩层如 FC(1024)将参数量从 1亿 压缩到 4000万。精度影响无需重新训练直接分解后进行单精度微调精度损失可控制在 0.2% 以内。4.替换为深度 可分离卷积Depthwise Separable Conv—— 针对卷积块这是最激进的轻量化方式将每个 3x3 Conv 替换为 深度卷积DW 逐点卷积PW。做法把 Conv3-64 替换为 DepthwiseConv2D(3x3) Conv2D(1x1)计算量可减少约 8~9倍。精度影响如果从头训练精度下降明显约5%~8%。但如果你先训练好原版VGG-16然后进行“知识蒸馏”用原版作为教师网络指导学生网络精度可维持在 71% 左右几乎不掉点。5.INT8 量化纯推理 阶段—— 完全不影响模型结构这是唯一能在“不改动任何网络结构”前提下实现轻量化的方法。做法训练完成后使用 TensorRT 或 PyTorch 的 torch.quantization 将权重和激活从 FP32 转为 INT8。效果模型体积缩小为原来的 1/4推理速度提升 2~3倍在CPU上尤为明显。精度影响通过“校准Calibration”数据集在ImageNet上INT8量化后Top-1精度损失通常 0.5%几乎可以忽略不计。六、感想本周在Tensorflow上继续学习调用预训练模型进一步熟悉了VGG-16模型架构的搭建。关于模型轻量化仅简单了解有待深入学习。
RELATED

相关推荐

ORA-1000 maximum open cursors exceeded 排查实录:从 open_cursors 到预编译 SQL 的配置骨架

ORA-1000 maximum open cursors exceeded 排查实录:从 open_cursors 到预编译 SQL 的配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/26 11:13:23
如何快速筛选出高质量的文献

如何快速筛选出高质量的文献

快速筛选高质量文献的核心是用“四层漏斗法”从海量结果里逐层过滤,用最低时间成本锁定真正有价值的核心文献,全程不用精读全文,就能把无效文献淘汰率提升到90%以上: 🎯 第一层:前置精准限定,从…

📅 2026/9/26 11:08:22
C#第二周学习的重点

C#第二周学习的重点

本文记录面向对象编程的核心概念:类与对象、构造方法、方法重载,以及继承与重写。通过一个「学生信息管理系统」的实战案例,逐步理解 OOP 思想。一、类与对象 1.1 引言 今天主要学习了面向对象编程。面向对象不同于面向过程:面向过…

📅 2026/9/26 11:08:22
MORE NEWS

更多资讯

📰

Atlas 300V 24G推理卡实战:基于CANN的YOLO模型部署全攻略

聊到Atlas,估计不少做AI算法落地的朋友第一反应是“这不是个数据库中间件吗?”或者“地图数据项目?”。但在AI硬件圈,Atlas正越来越多地指向华为昇腾AI计算产品线,尤其是Atlas 300V推理卡和Atlas 800训练服务器这类东西…

📰

PaddleX遥感图像解译平台实战:从模型训练到推理部署全流程

简介:遥感图像解译是计算机视觉在测绘与地理信息领域的重要应用,核心任务包括目标检测与语义分割。深度学习技术为自动化识别地物目标提供了可能,而PaddlePaddle作为国产开源框架,凭借其生态工具链显著降低了模型开发门槛。其中Pa…

📰

苹果成熟度检测数据集构建与YOLOv8训练全流程指南

简介:面向苹果成熟度检测的深度学习数据集,按YOLOV5目录结构组织,图像与标注一一对应,可直接用于目标检测模型训练。标签包含新鲜与腐败两类,采用YOLO相对坐标格式,训练集约七百张、验证集约三百张&#xf…

📰

LoRA/QLoRA实战:消费级显卡微调大模型全攻略

过去一年我做了不少行业模型的微调项目,最深的感触是:大模型参数高效微调这套技术路线,不是"省事的捷径",而是把大模型项目从天上拽回地上、让普通团队也能真正跑通闭环的基础设施。我说的"普通团队"&#xf…

📰

OpenAI又宕机了!从这次事故看AI服务的性能测试怎么做:TaoToken统一Key下的全链路压测配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

信贷违约预测实战:从特征工程到模型调参与评分卡构建

简介:面向计算机相关专业学生与从业者的个人信贷违约预测识别项目源码包,基于机器学习方法实现,包含完整源码与训练测试数据集,评审分达九十七分,经过严格调试可正常运行,适合期末课程设计、课程大作业或毕…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬