2025_10_13_12_动态内存

动态内存

本片援引自C++ Primer中的第12章,也是我复习的第6章

内存是我自学习高级语言以来最头疼的问题,今天可以借此篇好好梳理一番~

一、前言

我们编写的程序中所使用的对象都有严格定义的生存期。

例如:全局对象:程序启动时分配,结束时销毁。
局部对象:进入所在的程序块时被创建,离开时销毁。
静态对象(static):在使用前分配,在程序结束时销毁。

那么在内存中这些对象如何分配呢?
全局对象何静态对象在静态内存中存储,局部对象在栈内存中存储。由编译器自动创建和销毁。

C++还支持动态分配对象,这些对象被存储在“自由空间”——,由程序员创建和销毁(代码显式)。

日常生活中,静态内存和栈内存接触最多了,就不过多赘述了,接下来我就详细介绍一下动态内存吧~

二、动态内存和智能指针

2.1 概述

在C++中,动态内存通过一对运算符来完成:newdelete。(见后文)

使用动态内存容易出现问题

  • 忘记释放,导致内存泄露
  • 上有指针引用内存的情况,就释放了,导致引用非法内存的指针。

使用动态内存的原因

  • 程序不知道自己使用多少对象
  • 程序不知道所需对象的准确类型
  • 程序需要在多少个对象间共享数据

2.2 智能指针

2.2.1 概述

智能指针的行为类似常规指针,重点区别在于它负责自动释放所指向的对象。智能指针本质上就是一个封装好的自动化管理动态内存生命周期的类模板对象

类模板将在之后的篇章中详细介绍~

2.2.2 类型

两种类型,区别在于管理底层指针的方式。

  • shared_ptr
  • unique_ptr
2.2.3 使用

头文件:#include<memory>

在这里插入图片描述

在这里插入图片描述

2.2.4 shared_ptr

<1> 声明:必须提供指针可以指向的类型

// 声明
shared_ptr<string> p1;

<2> 初始化

  • 默认初始化:智能指针中保存着一个空指针。
  • 自己初始化:利用make_shared函数(见下文)

<3> 使用:和普通指针类似。解引用指针返回它指向的对象。允许多个指针指向同一个对象。

<4> 拷贝、赋值与销毁

  • 拷贝

    每个shared_ptr 都会记录有多少个其他shared_ptr 指向相同的对象,这是靠shared_ptr关联的计数器——引用计数实现的。每当拷贝shared_ptr时,计数器就会递增。

  • 赋值

    auto r = make_shared<int> (42);		// r指向的int只有一个引用者
    r = q;	// 给r赋值,令它指向另一个地址
    		// 递增q指向的对象的引用计数
    		// 递减r原来指向的对象的引用计数
    		// r原来指向的对象已没有引用者,会自动释放
    
  • 销毁

    shared_ptr会用所指向对象的析构函数完成销毁的,析构函数会递减它所指向的对象的引用计数,销毁对象,并释放它占用的内存和关联内存。(如果有其他shared_ptr 指向该内存,它就不会被释放)
    如果shared_ptr的计数器变为0,它就会自动释放自己所管理的对象。

2.2.5 make_shared函数

<1> 操作

该函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr

<2> 定义

make_shared用其参数来构造给定类型的对象,如果我们不传递任何参数,对象就会进行值初始化

shared_ptr<int> p3 = make_shared<int> (42);			// 值初始化为42
shared_ptr<int> p5 = make_shared<int> ();			// 值初始化为0(值初始化)
// 常用auto定义一个对象来保存make_shared结果
auto p6 = make_shared<vector<string>> ();
2.2.6 直接管理内存

<1> 概述

直接管理内存就是使用两个运算符newdelete

虽然在特殊工具与技术那一篇中已讲过,但是我在写本篇时回去回顾,发现还有很多细节没有考虑到,所以在此篇中详细讲讲~

newdelete本质就是运算符,但他们底层会调用全局的分配函数 operator new/delete进行内存的分配和释放。初始化和销毁数据都是靠传递给new 的参数的构造和析构函数。

<2> new

概述:在自由空间分配的内存是无名的,new 无法为其分配的对象命名,而是返回一个指向该对象的指针。动态分配的对象是默认初始化的。也可以对动态分配的对象进行值初始化。

// 默认初始化
int *p = new int(18);			// 值是未定义的
// 值初始化
string *q = new string();		// 有着良好的定义的值

const对象:可以隐式初始化

const int *p = new const int(18);		// 分配并初始化
const string *q = new const string;		// 隐式初始化,而且值已经不可改变了

内存耗尽new不能分配所要求的内存空间时,它会抛出一个类型为bad_alloc的异常(operator new函数抛出的)

定位new:不需要分配所需的内存,返回一个空指针,比如将nothrow的对象传递给new(如果不分配内存的情况下)就是定位new 的一种方式。

#include<new>
char *buffer = new char[sizeof(int)];
int *p = new(buffer) int(42);
p->~int();
delete[] buffer;			// 这里是释放字符数组,所以要加上"[]"。这取决于new的时候是不是数组
// 后面也会详细讲动态数组~

<3> delete

概述:将动态内存归还给系统。

细节delete接受一个指针,指向我们想要释放的对象(必须指向内存,或者它是一个空指针)。delete执行两个动作:销毁给定的指针指向的对象,释放对应的内存。

注意const对象的值不能被改变,但是可以销毁。
有时delete后,指针会变成空悬指针,仍然保存了释放的内存的地址。可以使其被赋予空指针。

<4> 易错点

  • 忘记delete内存
  • 使用已经释放的对象
  • 同一块内存释放两次
  • 坚持使用智能指针
2.2.7 shared_ptrnew结合使用

<1> 初始化

  • 如果不初始化一个智能指针,它就会被初始化为一个空指针。

  • 可以用new返回的指针来初始化智能指针。

  • 智能指针接受的参数是explicit的。

    shared_ptr<int> p1 = new int(18);		// 必须使用直接初始化的形式
    // 这里是需要编译器用一个new返回的int *来创建一个shared_ptr
    shared_ptr<int> p2(new int(18));		// √
    

在这里插入图片描述

在这里插入图片描述

<2> 注意

  • 不要混合使用普通指针和智能指针(我们无法知道智能指针负责的对象何时被销毁)
  • 不要使用get初始化另一个智能指针或为智能指针赋值

get是智能指针类型定义的函数,返回一个内置指针,指向智能指针管理的对象。使用get返回的指针的代码不能delete此指针。

<3> 其他操作

可以用reset将一个新指针赋予一个shared_ptr(改变底层对象之前,确保是当前对象仅有的用户)。reset会更新引用计数,它常和unique一起使用。

2.2.8 智能指针和异常
  • 在发生异常时,我们直接管理的内存是不会自动释放的。比如在newdelete之间发生了异常,内存就无法被释放了。
    解决方法:使用智能指针管理(shared_ptr)。
  • 智能指针和哑类:有些类没有析构函数(为C和C++两种语言设计的类)
    解决方法:可以使用shared_ptr避免内存泄露。
  • 使用自己的释放操作:如果使用的智能指针管理的资源不是new分配的内存,需要传递给它一个删除器。
2.2.9 unique_ptr

<1> 概述

一个unique_ptr指向一个给定的对象。(1V1

<2> 定义和初始化

定义:定义一个unique_ptr时,需要将其绑定到一个new返回的指针上。
初始化:直接初始化。

<3> 拷贝、赋值

不支持拷贝赋值。但可以调用release/reset将指针的所有权转移(除了const)。

  • release成员会返回unique_ptr保存的指针并将其置为空。release常被用来初始化另一个智能指针或给另一个智能指针赋值。
unique_ptr<string> p2(p1.release());		// 将所有权从p1转移给p2
  • reset接受一个可选的指针参数,令unique_ptr重新指向给定的指针,它会将目标指针原来的对象释放掉,接受新的指针。
unique_ptr<string> p3(new string("xcver"));
p2.reset(p3.release());
  • 可以拷贝或赋值一个将要被销毁的unique_ptr。编译器会执行移动语义。

<4> 传递删除器

可以重载unique_ptr中默认的删除器,这会影响unique_ptr的类型以及如何公祖奥,在unique_ptr指定类型后,提供删除器类型(在尖括号中)。

2.2.10 weak_ptr

<1> 概述

不控制所指向对象生存期的智能指针。

<2> 定义和初始化

定义:指向由一个shared_ptr管理的对象。当一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。即使有weak_ptr指向对象,对象还是会被释放。

初始化:用shared_ptr初始化。

auto p = make_shared<int> (42);
weak_ptr<int> wp(p);		// wp弱共享p

<3> 作用

  • 需要安全地访问一个可能已被 shared_ptr释放的资源,避免出现悬垂指针.
  • 两个或多个由 shared_ptr管理的对象相互持有对方的 shared_ptr,导致引用计数无法归零,从而引发内存泄漏。

三、动态数组

3.1 概述

3.1.1 目的或意义

一次分配/释放很多对象(对象数组)。

3.1.2 方式
  • new 表达式:分配并初始化一个对象数组。
  • allocator 类:分配和初始化分离
3.1.3 注意

大多数应用多使用标准库容器(如:vector)非不是动态分配的数组,容器的类可以使用默认版本的拷贝、赋值和操作,分配动态数组的类必须自定义自己版本的操作。所以容器更不容易出现内存管理的错误

3.2 new 和动态数组

3.2.1 定义
  • 类型名后要跟一对方括号
  • 要指明分配的对象的数目,大小必须是整型,不必是常量
  • 返回指向第一个对象的指针(元素类型的指针,不是数组类型)
// 使用get_size确定分配多少int
int *ptr = new int[get_size()];
// 可以使用表示数组类型的类型别名
typedef int arr[42];
int *p = new arr;`
3.2.2 初始化

<1> 方式

  • 在大小后跟一个空括号
  • 提供一个元素初始化器的花括号列表
    • 数目<元素数目,剩余元素进行值初始化
    • 数目>元素数目,new 表达式失败,不会分配任何内存
// 空括号版
int *ptr = new int[10]();
// 元素初始器版
int *ptr = new int[10]{10, 12, 4, 3};

<2> 注意

  • new表达式中**不能使用 auto**来推导数组类型。
  • 分配空数组是合法的。
    new 会返回一个合法的非空指针,我们可以像使用尾后迭代器(end())一样使用它,可以用这个指针进行比较操作,但是不能解引用(毕竟它不指向任何元素)
3.2.3 释放

<1> 方式

delete [] ptr;

<2> 细节

  • 每个使用到的元素被赋值了两次:默认初始化和赋值
  • 数组中的元素按逆序销毁。如果使用了数组别名,delete时也要加上方括号,因为delete会为数组中每个元素调用一次析构函数。
3.2.4 结合智能指针

<1> 定义

标准库提供了一个可以管理new分配的数组的**unique_ptr** 版本。

unique_ptr<int[]> up(new int[10]);

<2> 细节

  • up 销毁它管理的指针时,自动使用delete

  • 可以使用下标运算符访问数组中的元素

    for(size_t i = 0; i != 10; ++i)
        up[i] = i;
    

在这里插入图片描述

<3> 注意

  • shared_ptr 不直接支持管理动态数组,如果要使用,必须提供自己定义的删除器。
  • shared_ptr 未定义下标运算符,会影响如何访问数组中的元素。
  • 智能指针类型不支持指针算术运算(ptr + nptr++ptr2 - ptr1==, !=, >, <

3.3 allocator

3.3.1 概述

allocator是一个模板,定义在头文件memory中,将内存分配和对象构造分离开来,分配内存是原始的、未构造的。

有没有觉得很熟悉,new定位也有这个特性。回头看之前写的东西,觉得还是不够清楚,在这里再详细的剖析一下细节吧~

特性对比placement newallocator::construct
本质C++ 关键字/运算符(特殊的 new表达式)std::allocator类模板的成员函数
核心功能在指定内存地址调用对象的构造函数在分配的内存位置使用拷贝构造函数初始化对象
构造函数支持支持对象的任何构造函数(无参、有参等)传统上主要使拷贝构造函数(通过传入一个现有对象来构造)
内存来源任何已分配的原始内存(堆、栈、内存池等)通常来源于 allocator自身通过 allocate()分配的内存
析构方式需要显式调用对象的析构函数(如 obj->~T();使用 allocatordestroy成员函数来析构对象
使用场景更底层,提供最大灵活性,常用于内存池、自定义内存管理、性能极致优化的场景更高级、更安全,通常与标准库容器(如 std::vector)及其自定义分配器紧密集成
类型安全性相对较低,需要开发者自行确保内存大小和对齐方式正确相对较高,因其与特定的 allocator类型关联
3.3.2 定义

定义一个allocator 对象,必须指明可以分配的对象类型。

allocator<string> alloc;				// 可以分配string的allocator对象
auto const p = alloc.allocate(n);		// 分配n个未初始化的string
3.3.3 使用过程

为了使用allocate返回的内存,我们必须用construct构造对象,construct 成员函数一个指针和0/多个额外参数。
函数destroy 接受一个指针,对指向的对象执行析构函数。(只能对真正构造了的元素进行destroy操作),逆序删除元素。
释放内存通过deallocate,我们传递给deallocate的指针不能为空。

在这里插入图片描述

3.3.4 扩展

allocate类中还定义了两个伴随算法,可以在未初始化内存中创建对象。

在这里插入图片描述

我对内存的理解仍然任重道远,希望各位道友批评指正~

为什么中间漏了几十分钟的log? yuanhaixiong@yuanhaixiong-PC:~/machine/Log/#K1-8G-KASAN版本monkey异常停止0806/debuglogger/mobilelog$ ls APLog_2025_0806_173133__3 APLog_2025_0807_065857__5 APLog_2025_0807_080020__7 APLog_2025_0807_112654__9 APLog_2025_0807_130603__11 APLog_2025_0807_134712__13 APLog_2025_0807_153818__15 APLog_2025_0807_042752__4 APLog_2025_0807_073742__6 APLog_2025_0807_111445__8 APLog_2025_0807_121702__10 APLog_2025_0807_134043__12 APLog_2025_0807_150142__14 file_tree.txt yuanhaixiong@yuanhaixiong-PC:~/machine/Log/#K1-8G-KASAN版本monkey异常停止0806/debuglogger/mobilelog$ tail APLog_2025_0807_150142__14/ atf_log_8__2025_0807_151258 crash_log_6__2025_0807_151258 main_log_1__2025_0807_151029 pl_lk sspm_log_12__2025_0807_151258 bootprof events_log_4__2025_0807_151258 main_log_2__2025_0807_151258 properties sys_log_5__2025_0807_151258 bsp_log_10__2025_0807_151258 gz_log_9__2025_0807_151258 mblog_history radio_log_3__2025_0807_151258 connsys_picus_log_14__2025_0807_151258 kernel_log_7__2025_0807_151258 mcupm_log_13__2025_0807_151258 scp_log_11__2025_0807_151258 yuanhaixiong@yuanhaixiong-PC:~/machine/Log/#K1-8G-KASAN版本monkey异常停止0806/debuglogger/mobilelog$ tail APLog_2025_0807_150142__14/main_log_2__2025_0807_151258 08-07 15:12:58.266055 1388 1388 D BufferQueueConsumer: [](id:56c00000a64,api:0,p:-1,c:1388) connect: controlledByApp=false 08-07 15:12:58.267110 1388 1388 D BLASTBufferQueue: [VRI[0 fl=}]#2576](f:0,a:0) constructor() 08-07 15:12:58.267446 1388 1388 D BLASTBufferQueue: [VRI[0 fl=}]#2576](f:0,a:0) update width=1080 height=2412 format=-2 mTransformHint=0 08-07 15:12:58.268282 1478 1671 I PowerHalWrapper: amsBoostNotify pid:24443,activity:com.android.searchlauncher.SearchLauncher, package:com.android.launcher3, mProcessCreatePackcom.google.android.apps.safetyhub 08-07 15:12:58.268479 1478 1671 I PowerHalWrapper: state: 1 08-07 15:12:58.269953 1478 1671 I mtkpower_client: [PowerHal_Wrap_notifyAppState] com.android.launcher3/com.android.searchlauncher.SearchLauncher pid=24443 activityId:211372178 state:1 08-07 15:12:58.270392 1478 1671 I mtkpower_client: [Legacy][PowerHal_Wrap_notifyAppState] com.android.launcher3/com.android.searchlauncher.SearchLauncher pid=24443 state:211372178 08-07 15:12:58.271280 6355 6355 I Monkey : :Sending Touch (ACTION_DOWN): 0:(638.0,2182.0) 08-07 15:12:58.271369 1388 1388 I cioz : (REDACTED) onApplyWindowInsets: systemWindowInsets=%s 08-07 15:12:58.271549 897 954 I libPowerHal: [perfNotifyAppState] pack:com.android.launcher3, act:com.android.searchlauncher.SearchLauncher, state:1, pid:24443, uid:1000, fps:-1 yuanhaixiong@yuanhaixiong-PC:~/machine/Log/#K1-8G-KASAN版本monkey异常停止0806/debuglogger/mobilelog$ ls APLog_2025_0806_173133__3 APLog_2025_0807_065857__5 APLog_2025_0807_080020__7 APLog_2025_0807_112654__9 APLog_2025_0807_130603__11 APLog_2025_0807_134712__13 APLog_2025_0807_153818__15 APLog_2025_0807_042752__4 APLog_2025_0807_073742__6 APLog_2025_0807_111445__8 APLog_2025_0807_121702__10 APLog_2025_0807_134043__12 APLog_2025_0807_150142__14 file_tree.txt yuanhaixiong@yuanhaixiong-PC:~/machine/Log/#K1-8G-KASAN版本monkey异常停止0806/debuglogger/mobilelog$ head APLog_2025_0807_153818__15/ atf_log_7__2025_0807_155133 crash_log_5__2025_0807_155133 main_log_1__2025_0807_155133 properties sys_log_4__2025_0807_155133 bootprof events_log_3__2025_0807_155133 mblog_history radio_log_2__2025_0807_155133 bsp_log_9__2025_0807_155133 gz_log_8__2025_0807_155133 mcupm_log_12__2025_0807_155133 scp_log_10__2025_0807_155133 connsys_picus_log_13__2025_0807_155133 kernel_log_6__2025_0807_155133 pl_lk sspm_log_11__2025_0807_155133 yuanhaixiong@yuanhaixiong-PC:~/machine/Log/#K1-8G-KASAN版本monkey异常停止0806/debuglogger/mobilelog$ head APLog_2025_0807_153818__15/main_log_1__2025_0807_155133 ----- timezone:Asia/Shanghai 08-07 15:37:42.020551 1899 1899 D BLASTBufferQueue: [VRI[VolumeDialogImpl]#20808](f:0,a:0) constructor() 08-07 15:37:42.020644 1899 1899 D BLASTBufferQueue: [VRI[VolumeDialogImpl]#20808](f:0,a:0) update width=192 height=1584 format=-2 mTransformHint=0 08-07 15:37:42.022698 1899 2022 D BufferQueueProducer: [VRI[VolumeDialogImpl]#20808(BLAST Consumer)20808](id:76b000051cf,api:1,p:1899,c:1899) connect: api=1 producerControlledByApp=true 08-07 15:37:42.038344 1899 2022 D BLASTBufferQueue: [VRI[VolumeDialogImpl]#20808](f:0,a:1) acquireNextBufferLocked size=192x1584 mFrameNumber=1 applyTransaction=true mTimestamp=80052119459001(auto) mPendingTransactions.size=0 graphicBufferId=8156143212544 transform=0 08-07 15:37:42.039933 934 986 E surfaceflinger: == MALI DEBUG ===eglp_winsys_populate_image_templates ==12288 08-07 15:37:42.049390 1478 1606 E system_server: No package ID ff found for resource ID 0xffffffff. 08-07 15:37:42.058021 934 1710 I BufferQueueDebug: [Surface(name=e81a44d VolumeDialogImpl)/@0x36c1005 - animation-leash of window_animation#399493](this:0xb40000777fcdb730,id:-1,api:0,p:-1,c:-1) BufferQueue core=(934:/system/bin/surfaceflinger) 08-07 15:37:42.067688 1899 1899 D BLASTBufferQueue: [VRI[VolumeDialogImpl]#20808](f:0,a:1) update width=192 height=1392 format=-2 mTransformHint=0 08-07 15:37:42.069336 1899 2022 D BufferQueueProducer: [VRI[VolumeDialogImpl]#20808(BLAST Consumer)20808](id:76b000051cf,api:1,p:1899,c:1899) disconnect: api 1 yuanhaixiong@yuanhaixiong-PC:~/machine/Log/#K1-8G-KASAN版本monkey异常停止0806/debuglogger/mobilelog$
08-21
由[2025-10-17 07:11:14] client_mgmt: ERR: fill_missed_re_client_list client(08-62-66-29-E0-15) found:true [2025-10-17 07:11:16] client_mgmt: ERR: fill_missed_re_client_list client(74-86-E2-0E-EC-5C) found:true [2025-10-17 07:11:16] MemTotal: 493640 kB [2025-10-17 07:11:16] MemFree: 87916 kB [2025-10-17 07:11:16] MemAvailable: 91880 kB [2025-10-17 07:11:16] Buffers: 8520 kB [2025-10-17 07:11:16] Cached: 38036 kB [2025-10-17 07:11:16] SwapCached: 0 kB [2025-10-17 07:11:16] Active: 97864 kB [2025-10-17 07:11:16] Inactive: 7252 kB [2025-10-17 07:11:16] Active(anon): 65636 kB [2025-10-17 07:11:16] Inactive(anon): 504 kB [2025-10-17 07:11:16] Active(file): 32228 kB [2025-10-17 07:11:16] Inactive(file): 6748 kB [2025-10-17 07:11:16] Unevictable: 5652 kB [2025-10-17 07:11:16] Mlocked: 0 kB [2025-10-17 07:11:16] SwapTotal: 0 kB [2025-10-17 07:11:16] SwapFree: 0 kB [2025-10-17 07:11:16] Dirty: 0 kB [2025-10-17 07:11:16] Writeback: 0 kB [2025-10-17 07:11:16] AnonPages: 64136 kB [2025-10-17 07:11:16] Mapped: 16828 kB [2025-10-17 07:11:16] Shmem: 1928 kB [2025-10-17 07:11:16] KReclaimable: 8824 kB [2025-10-17 07:11:16] Slab: 110184 kB [2025-10-17 07:11:16] SReclaimable: 8824 kB [2025-10-17 07:11:16] SUnreclaim: 101360 kB [2025-10-17 07:11:16] KernelStack: 2832 kB [2025-10-17 07:11:16] PageTables: 1540 kB [2025-10-17 07:11:16] NFS_Unstable: 0 kB [2025-10-17 07:11:16] Bounce: 0 kB [2025-10-17 07:11:16] WritebackTmp: 0 kB [2025-10-17 07:11:16] CommitLimit: 246820 kB [2025-10-17 07:11:16] Committed_AS: 84196 kB [2025-10-17 07:11:16] VmallocTotal: 262930368 kB [2025-10-17 07:11:16] VmallocUsed: 52556 kB [2025-10-17 07:11:16] VmallocChunk: 0 kB [2025-10-17 07:11:16] Percpu: 656 kB [2025-10-17 07:11:16] client_mgmt: ERR: fill_missed_re_client_list client(08-62-66-29-E0-15) found:true [2025-10-17 07:11:31] client_mgmt: ERR: fill_missed_re_client_list client(74-86-E2-0E-EC-5C) found:true [2025-10-17 07:11:31] mdns limit set to 64 [2025-10-17 07:11:40] client_mgmt: ERR: fill_missed_re_client_list client(08-62-66-29-E0-15) found:true [2025-10-17 07:11:46] client_mgmt: ERR: fill_missed_re_client_list client(74-86-E2-0E-EC-5C) found:true [2025-10-17 07:11:46] mdns limit set to 32 [2025-10-17 07:11:49] mdns limit set to 16 [2025-10-17 07:11:58] conn-indicator: INFO: Event: inet.request [2025-10-17 07:12:00] client_mgmt: ERR: fill_missed_re_client_list client(08-62-66-29-E0-15) found:true [2025-10-17 07:12:02] client_mgmt: ERR: fill_missed_re_client_list client(74-86-E2-0E-EC-5C) found:true [2025-10-17 07:12:02] conn-indicator: INFO: Event: inet.request [2025-10-17 07:12:05] mdns limit set to 10 [2025-10-17 07:12:07] Mem: 404888K used, 88752K free, 0K shrd, 2608K buff, 548320794672K cached [2025-10-17 07:12:16] CPU: 0% usr 0% sys 0% nic 97% idle 0% io 0% irq 2% sirq [2025-10-17 07:12:16] Load average: 5.17 5.23 5.26 1/172 30077 [2025-10-17 07:12:16] PID PPID USER STAT VSZ %VSZ %CPU COMMAND [2025-10-17 07:12:16] 30077 11638 root R 1864 0% 2% top n1 [2025-10-17 07:12:16] 13128 1 root S 19396 4% 0% /usr/bin/client_mgmt [2025-10-17 07:12:16] 22109 1 root S 16376 3% 0% /usr/bin/app-classifier -p 10 -q 16 [2025-10-17 07:12:16] 15511 1 root S 10640 2% 0% {check_temp.sh} /bin/sh /usr/sbin/che [2025-10-17 07:12:16] 15807 1 root S 6684 1% 0% /usr/bin/iot-tapo [2025-10-17 07:12:16] 5546 1 root S 6544 1% 0% /usr/sbin/hostapd -g /var/run/hostapd [2025-10-17 07:12:16] 1595 1 root S 6436 1% 0% /usr/bin/cloud-brd -c /etc/cloud_conf [2025-10-17 07:12:16] 2667 1 root S 6420 1% 0% /usr/sbin/wpa_supplicant -g /var/run/ [2025-10-17 07:12:16] 19168 1 root S 6272 1% 0% /usr/bin/tss [2025-10-17 07:12:16] 15641 1 root S 6188 1% 0% /usr/bin/iot-netdev [2025-10-17 07:12:16] 13213 1 root S 5232 1% 0% /usr/bin/cloud-https [2025-10-17 07:12:16] 31842 1 root S 4928 1% 0% /usr/sbin/miniupnpd -f /var/etc/miniu [2025-10-17 07:12:16] 13222 1 root S 4764 1% 0% /usr/bin/cloud-proxy -c /etc/cloud_co [2025-10-17 07:12:16] 5531 1 root S 4752 1% 0% /usr/bin/tpapsvr [2025-10-17 07:12:16] 1429 1 root S 4620 1% 0% /usr/bin/tmpcd -d 5 [2025-10-17 07:12:16] 1715 1 root S 4556 1% 0% /usr/sbin/uhttpd -f -h /www -r BE25 - [2025-10-17 07:12:16] 2279 1 root S 4512 1% 0% /sbin/logd -S 1024 [2025-10-17 07:12:16] 11431 1 root S 4348 1% 0% /usr/sbin/tfstats [2025-10-17 07:12:16] 15273 1 root S 4256 1% 0% /usr/sbin/uhttpd -f -p 127.0.0.1:2000 [2025-10-17 07:12:16] 1016 1 root S 3812 1% 0% /usr/bin/apsd -c /tmp/apsd.json 变更为 [2025-10-20 15:29:12] Mem: 410768K used, 82872K free, 0K shrd, 2592K buff, 547716700208K cached [2025-10-20 15:29:13] CPU: 2% usr 4% sys 0% nic 88% idle 0% io 0% irq 4% sirq [2025-10-20 15:29:13] Load average: 5.39 5.35 5.31 2/171 23023 [2025-10-20 15:29:13] PID PPID USER STAT VSZ %VSZ %CPU COMMAND [2025-10-20 15:29:13] 11431 1 root R 4348 1% 2% /usr/sbin/tfstats [2025-10-20 15:29:13] 13128 1 root S 24152 5% 0% /usr/bin/client_mgmt [2025-10-20 15:29:13] 22109 1 root S 16376 3% 0% /usr/bin/app-classifier -p 10 -q 16 [2025-10-20 15:29:13] 15511 1 root S 11656 2% 0% {check_temp.sh} /bin/sh /usr/sbin/che [2025-10-20 15:29:13] 15807 1 root S 6684 1% 0% /usr/bin/iot-tapo [2025-10-20 15:29:13] 5546 1 root S 6544 1% 0% /usr/sbin/hostapd -g /var/run/hostapd [2025-10-20 15:29:13] 1595 1 root S 6436 1% 0% /usr/bin/cloud-brd -c /etc/cloud_conf [2025-10-20 15:29:13] 2667 1 root S 6420 1% 0% /usr/sbin/wpa_supplicant -g /var/run/ [2025-10-20 15:29:13] 19168 1 root S 6272 1% 0% /usr/bin/tss [2025-10-20 15:29:13] 15641 1 root S 6188 1% 0% /usr/bin/iot-netdev [2025-10-20 15:29:13] 13213 1 root S 5232 1% 0% /usr/bin/cloud-https [2025-10-20 15:29:13] 15368 1 root S 4836 1% 0% /usr/sbin/miniupnpd -f /var/etc/miniu [2025-10-20 15:29:13] 13222 1 root S 4764 1% 0% /usr/bin/cloud-proxy -c /etc/cloud_co [2025-10-20 15:29:13] 5531 1 root S 4752 1% 0% /usr/bin/tpapsvr [2025-10-20 15:29:13] 1429 1 root S 4640 1% 0% /usr/bin/tmpcd -d 5 [2025-10-20 15:29:13] 1715 1 root S 4556 1% 0% /usr/sbin/uhttpd -f -h /www -r BE25 - [2025-10-20 15:29:13] 2279 1 root S 4512 1% 0% /sbin/logd -S 1024 [2025-10-20 15:29:13] 15273 1 root S 4256 1% 0% /usr/sbin/uhttpd -f -p 127.0.0.1:2000 [2025-10-20 15:29:13] 1016 1 root S 3812 1% 0% /usr/bin/apsd -c /tmp/apsd.json [2025-10-20 15:29:13] 16002 1 root S 3256 1% 0% /usr/bin/matter [2025-10-20 15:29:13] MemTotal: 493640 kB [2025-10-20 15:30:13] MemFree: 84332 kB [2025-10-20 15:30:13] MemAvailable: 88356 kB [2025-10-20 15:30:13] Buffers: 8520 kB [2025-10-20 15:30:13] Cached: 38072 kB [2025-10-20 15:30:13] SwapCached: 0 kB [2025-10-20 15:30:13] Active: 102884 kB [2025-10-20 15:30:13] Inactive: 7240 kB [2025-10-20 15:30:13] Active(anon): 70632 kB [2025-10-20 15:30:13] Inactive(anon): 512 kB [2025-10-20 15:30:13] Active(file): 32252 kB [2025-10-20 15:30:13] Inactive(file): 6728 kB [2025-10-20 15:30:13] Unevictable: 5652 kB [2025-10-20 15:30:13] Mlocked: 0 kB [2025-10-20 15:30:13] SwapTotal: 0 kB [2025-10-20 15:30:13] SwapFree: 0 kB [2025-10-20 15:30:13] Dirty: 0 kB [2025-10-20 15:30:13] Writeback: 0 kB [2025-10-20 15:30:13] AnonPages: 69224 kB [2025-10-20 15:30:13] Mapped: 16824 kB [2025-10-20 15:30:13] Shmem: 1960 kB [2025-10-20 15:30:13] KReclaimable: 8936 kB [2025-10-20 15:30:13] Slab: 111112 kB [2025-10-20 15:30:13] SReclaimable: 8936 kB [2025-10-20 15:30:13] SUnreclaim: 102176 kB [2025-10-20 15:30:13] KernelStack: 2788 kB [2025-10-20 15:30:13] PageTables: 1480 kB [2025-10-20 15:30:13] NFS_Unstable: 0 kB [2025-10-20 15:30:13] Bounce: 0 kB [2025-10-20 15:30:13] WritebackTmp: 0 kB [2025-10-20 15:30:13] CommitLimit: 246820 kB [2025-10-20 15:30:13] Committed_AS: 89732 kB [2025-10-20 15:30:13] VmallocTotal: 262930368 kB [2025-10-20 15:30:13] VmallocUsed: 52528 kB [2025-10-20 15:30:13] VmallocChunk: 0 kB [2025-10-20 15:30:13] Percpu: 656 kB 内存增长在哪里
10-21
""" import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties # 指定支持中文的字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows 系统下使用黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 # 定义代码 code =""" __author__ = 'Eric' #导包 import tensorflow as tf import numpy as np import matplotlib.pyplot as plt from tensorflow.keras.layers import Conv2D,MaxPooling2D,Input,GlobalMaxPooling2D,Dense,Flatten,Dropout,Lambda from tensorflow.keras.models import Model from tensorflow.keras.regularizers import L2 from tensorflow.keras.callbacks import ReduceLROnPlateau#用来做学习率回调 from tensorflow.keras.initializers import RandomNormal,Zeros#参数初始化 import os import sys ''' 1、数据预处理 ''' ''' 数据集格式: dataset/ ├── train/ │ ├── class1/ │ │ ├── img1.jpg │ │ ├── img2.jpg │ │ └── ... │ ├── class2/ │ │ ├── img1.jpg │ │ ├── img2.jpg │ │ └── ... │ └── ... └── validation/ ├── class1/ │ ├── img1.jpg │ ├── img2.jpg │ └── ... ├── class2/ │ ├── img1.jpg │ ├── img2.jpg │ └── ... └── ... ''' #TensorFlow 默认会预分配显存,但你可以通过设置 allow_growth 为 True,让 TensorFlow 按需分配显存。 # 设置动态内存分配 gpus = tf.config.experimental.list_physical_devices('GPU') if gpus: try: for gpu in gpus: tf.config.experimental.set_memory_growth(gpu, True) print("显存动态分配成功!") except RuntimeError as e: print(e) #①指定GPU使用量,占用GPU90%的显存 for gpu in gpus: tf.config.experimental.per_process_gpu_memory_fraction = 0.9 ''' # 全局设置默认设备为 CPU tf.config.experimental.set_visible_devices([], 'GPU') ''' #TF_GPU_ALLOCATOR=cuda_malloc_async,改善显存环境,减少显存碎片化 #os.environ['TF_GPU_ALLOCATOR'] = 'cuda_malloc_async' def loadDataset(): # 使用 CPU 进行图像预处理 with tf.device('/cpu:0'): # 定义数据集路径 #train_dir = 'dataset/train' #validation_dir = 'dataset/validation' train_dir = r"D:\2025College Student Innovation and Entrepreneurship Project\project\VGG\dataset\data\train" validation_dir = r"D:\2025College Student Innovation and Entrepreneurship Project\project\VGG\dataset\data\validation" test_dir = r"D:\2025College Student Innovation and Entrepreneurship Project\project\VGG\dataset\data\test" ''' #检查是否为UTF-8编码格式 def is_valid_utf8(s): try: s.encode('utf-8') return True except UnicodeEncodeError: return False # 检查训练集 for class_name in os.listdir(train_dir): class_dir = os.path.join(train_dir, class_name) if not is_valid_utf8(class_name): print(f"Invalid UTF-8 class name: {class_name}") for image_name in os.listdir(class_dir): if not is_valid_utf8(image_name): print(f"Invalid UTF-8 image name: {image_name}") # 检查验证集 for class_name in os.listdir(validation_dir): class_dir = os.path.join(validation_dir, class_name) if not is_valid_utf8(class_name): print(f"Invalid UTF-8 class name: {class_name}") for image_name in os.listdir(class_dir): if not is_valid_utf8(image_name): print(f"Invalid UTF-8 image name: {image_name}") print("OK") ''' # 获取所有类别名称 class_names = sorted(os.listdir(train_dir)) # 假设训练集和验证集的类别名称一致 class_to_label = {class_name: idx for idx, class_name in enumerate(class_names)}#类别名称与索引标签映射 # 定义图像加载函数 def load_image(image_path, label): with tf.device('/cpu:0'): image = tf.io.read_file(image_path) # 读取图像文件 image = tf.image.decode_image(image, channels=3) # 解码图像 # 显式设置图像的形状 image.set_shape([None, None, 3]) return image, label #解决TF对象不可哈希的问题,因此不能直接用作字典的键 def convert_label(image, label): with tf.device('/cpu:0'): label = label.numpy().decode('utf-8', errors='ignore') # 忽略解码错误 label = class_to_label[label] # 将类别名称转换为整数标签 return image, tf.constant(label) #1、 定义动态调整图像尺寸的函数【单尺度,各向同性缩放】(S=256,S=384) #先训练S=256,然后训练S=384(权重迁移),第二次训练学习率为0.001 ''' ratio=S/min(height,width) new_height=round(height×ratio) new_width=round(width×ratio) ''' def dynamic_resize1(image, label, S=256,flip_rate = 0.5,max_delta=0.2): with tf.device('/cpu:0'): # 获取图像的原始尺寸 original_shape = tf.shape(image) original_height = original_shape[0] original_width = original_shape[1] # 计算新的尺寸 # 保持宽高比例,使最短边等于 S ratio = tf.cast(S, tf.float32) / tf.cast(tf.minimum(original_height, original_width), tf.float32) new_height = tf.cast(tf.round(tf.cast(original_height, tf.float32) * ratio), tf.int32) new_width = tf.cast(tf.round(tf.cast(original_width, tf.float32) * ratio), tf.int32) # 调整图像尺寸 image = tf.image.resize(image, (new_height, new_width)) # 裁剪图像到 S x S # 选择中心裁剪或随机裁剪 if S == 256 or S == 384: # 随机裁剪 image = tf.image.random_crop(image, (224, 224, 3)) else: # 中心裁剪 image = tf.image.resize_with_crop_or_pad(image, 224, 224) # 随机决定是否翻转(50% 概率) if tf.random.uniform(()) > flip_rate: image = tf.image.flip_left_right(image) #随机RGB颜色偏移(直接调整亮度) image=tf.image.random_brightness(image, max_delta=max_delta) return image, label #2、 定义动态调整图像尺寸的函数【多尺度,各向同性缩放】(Smin=256,Smax=512) #先用相同配置网络训练S=384,在用权重迁移训练多尺度网络 def dynamic_resize2(image, label, Smin=256,Smax=512): with tf.device('/cpu:0'): # 随机选择一个尺寸 new_size = tf.random.uniform(shape=[], minval=Smin, maxval=Smax, dtype=tf.int32) # 调整图像尺寸 image = tf.image.resize(image, (new_size, new_size)) # 裁剪图像到 S x S # 选择中心裁剪或随机裁剪 if Smin == 256 and Smax == 512: # 随机裁剪 image = tf.image.random_crop(image, (224, 224, 3)) else: # 中心裁剪 image = tf.image.resize_with_crop_or_pad(image, 224, 224) return image, label # 加载训练集 train_image_paths = [] train_labels = [] for class_name in class_names: class_dir = os.path.join(train_dir, class_name) for image_name in os.listdir(class_dir): image_path = os.path.join(class_dir, image_name) train_image_paths.append(image_path) train_labels.append(class_name) # 加载验证集 validation_image_paths = [] validation_labels = [] for class_name in class_names: class_dir = os.path.join(validation_dir, class_name) for image_name in os.listdir(class_dir): image_path = os.path.join(class_dir, image_name) validation_image_paths.append(image_path) validation_labels.append(class_name) #加载测试集 test_image_paths = [] test_labels = [] for class_name in class_names: class_dir = os.path.join(test_dir, class_name) for image_name in os.listdir(class_dir): image_path = os.path.join(class_dir, image_name) test_image_paths.append(image_path) test_labels.append(class_name) # 创建训练集数据集 train_dataset = tf.data.Dataset.from_tensor_slices((train_image_paths, train_labels)) #print(train_dataset) # 使用 map 函数对每个路径调用 load_image 函数 train_dataset = train_dataset.map(load_image,num_parallel_calls=tf.data.AUTOTUNE)#map函数默认在图模式下运行 #print(train_dataset) train_dataset = train_dataset.map(lambda x, y: dynamic_resize1(x, y), num_parallel_calls=tf.data.AUTOTUNE) #print(train_dataset) train_dataset = train_dataset.map(lambda x, y: tf.py_function(convert_label, [x, y], [tf.float32, tf.int32]), num_parallel_calls=tf.data.AUTOTUNE) #print(train_dataset)#tf.data.Dataset 的 shapes 属性描述的是数据集中每个元素的形状,而不是整个数据集的综合形状。 # 创建验证集数据集 validation_dataset = tf.data.Dataset.from_tensor_slices((validation_image_paths, validation_labels)) validation_dataset = validation_dataset.map(load_image, num_parallel_calls=tf.data.AUTOTUNE) validation_dataset = validation_dataset.map(lambda x, y: dynamic_resize1(x, y), num_parallel_calls=tf.data.AUTOTUNE) validation_dataset = validation_dataset.map(lambda x, y: tf.py_function(convert_label, [x, y], [tf.float32, tf.int32]), num_parallel_calls=tf.data.AUTOTUNE) # 创建测试集数据集 test_dataset = tf.data.Dataset.from_tensor_slices((test_image_paths, test_labels)) test_dataset = test_dataset.map(load_image, num_parallel_calls=tf.data.AUTOTUNE) test_dataset = test_dataset.map(lambda x, y: dynamic_resize1(x, y), num_parallel_calls=tf.data.AUTOTUNE) test_dataset = test_dataset.map(lambda x, y: tf.py_function(convert_label, [x, y], [tf.float32, tf.int32]), num_parallel_calls=tf.data.AUTOTUNE) #显式指定图片尺寸 train_dataset = train_dataset.map( lambda x, y: (tf.reshape(x, (224, 224, 3)), tf.reshape(y,())), num_parallel_calls=tf.data.AUTOTUNE ) validation_dataset = validation_dataset.map( lambda x, y: (tf.reshape(x, (224, 224, 3)), tf.reshape(y,())), num_parallel_calls=tf.data.AUTOTUNE ) test_dataset = test_dataset.map( lambda x, y: (tf.reshape(x, (224, 224, 3)), tf.reshape(y,())), num_parallel_calls=tf.data.AUTOTUNE ) # 批量处理和预取 train_dataset = train_dataset.cache().shuffle(1000).batch(128).prefetch(buffer_size=tf.data.AUTOTUNE) validation_dataset = validation_dataset.cache().batch(128).prefetch(buffer_size=tf.data.AUTOTUNE) test_dataset = test_dataset.cache().batch(128).prefetch(buffer_size=tf.data.AUTOTUNE) #print(train_dataset) #print(validation_dataset) #print(test_dataset) #cache方法是 TensorFlow 中的一个优化工具,用于缓存数据集的内容。它可以在首次迭代数据集时将数据加载到内存中,从而在后续迭代中直接从内存中读取数据,而不是每次都从磁盘重新加载。这可以显著提高数据加载的效率,尤其是在数据集较大且多次迭代时。 for batch in train_dataset.take(1): print(batch[0].shape, batch[1].shape) # 查看真实形状 ''' #print(train_dataset) # 可视化加载的图像(训练集) for images, labels in train_dataset.take(1): for i in range(9): plt.subplot(3, 3, i + 1) plt.imshow(images[i].numpy().astype("uint8")) plt.title(f'Label: {labels[i].numpy()}') # 显示整数标签 plt.axis("off") plt.savefig("train_dataset.png") plt.show() break # 可视化加载的图像(验证集) for images, labels in validation_dataset.take(1): for i in range(9): plt.subplot(3, 3, i + 1) plt.imshow(images[i].numpy().astype("uint8")) plt.title(f'Label: {labels[i].numpy()}') # 显示整数标签 plt.axis("off") plt.savefig("validation_dataset.png") plt.show() break ''' return train_dataset,validation_dataset,test_dataset """ 2、网络架构 """ #定义A模型架构 #11 weight layers #对于第一个网络,每个网络层权重用正态分布进行初始化,偏置全部初始化为0 def VGG_A(inputs): #第一部分卷积 #Input 224x224x3 #64个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 224x224x64 #初始化偏置为0,使用均值为0方差为0.01(10**(-2)的正态分布进行初始化) x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same', kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(inputs) #第一部分池化 #Input 224x224x64 #Output 112x112x64 x = MaxPooling2D()(x) #第二部分卷积 #Input 112x112x64 #128个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 112x112x128 #初始化偏置为0,使用均值为0方差为0.01(10**(-2)的正态分布进行初始化) x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same', kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x) #第二部分最大池化 #Input 112x112x128 #Output 56x56x128 x = MaxPooling2D()(x) #第三部分卷积 #Input 56x56x128 #Output 56x56x256 #初始化偏置为0,使用均值为0方差为0.01(10**(-2)的正态分布进行初始化) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same', kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same', kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x) #第三部分最大池化 #Input 56x56x256 #Output 28x28x256 x = MaxPooling2D()(x) #第四部分卷积 #Input 28x28x256 #Output 28x28x512 #初始化偏置为0,使用均值为0方差为0.01(10**(-2)的正态分布进行初始化) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same', kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same', kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x) #第四部分最大池化 #Input 28x28x512 #Output 14x14x512 x = MaxPooling2D()(x) #第五部分卷积 #Input 14x14x512 #Output 14x14x512 #初始化偏置为0,使用均值为0方差为0.01(10**(-2)的正态分布进行初始化) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same', kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same', kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x) #第五部分最大池化 #Input 14x14x512 #Output 7x7x512 x = MaxPooling2D()(x) #初始化偏置为0,使用均值为0方差为0.01(10**(-2)的正态分布进行初始化) #三个全连接层(其中有添加Flatten层作为数据展平,不过论文中没有写) x = Flatten()(x) x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)), kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x) x = tf.nn.dropout(x, 0.5) # 应用Dropout x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)), kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x)#前两个全连接层添加系数为5*(10)**(-4)的L2正则化 x = tf.nn.dropout(x, 0.5) # 应用Dropout outputs = Dense(1000,activation = 'softmax', kernel_initializer=RandomNormal(mean=0.0, stddev=0.01), bias_initializer=Zeros())(x) #返回输出值 return outputs #定义A_LRN模型架构 #11 weight layers #对于其他网络,与前一网络重合部分沿用前一网络权重,其他网络层权重用正态分布进行初始化,偏置全部初始化为0 def VGG_A_LRN(inputs): #第一部分卷积 #Input 224x224x3 #64个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 224x224x64 x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(inputs) #添加LRN归一化层 x = tf.nn.local_response_normalization(x) #第一部分池化 #Input 224x224x64 #Output 112x112x64 x = MaxPooling2D()(x) #第二部分卷积 #Input 112x112x64 #128个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 112x112x128 x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第二部分最大池化 #Input 112x112x128 #Output 56x56x128 x = MaxPooling2D()(x) #第三部分卷积 #Input 56x56x128 #Output 56x56x256 x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第三部分最大池化 #Input 56x56x256 #Output 28x28x256 x = MaxPooling2D()(x) #第四部分卷积 #Input 28x28x256 #Output 28x28x512 x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第四部分最大池化 #Input 28x28x512 #Output 14x14x512 x = MaxPooling2D()(x) #第五部分卷积 #Input 14x14x512 #Output 14x14x512 x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第五部分最大池化 #Input 14x14x512 #Output 7x7x512 x = MaxPooling2D()(x) #三个全连接层(其中有添加Flatten层作为数据展平,不过论文中没有写) x = Flatten()(x) x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x) x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x)#前两个全连接层添加系数为5*(10)**(-4)的L2正则化 x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 outputs = Dense(1000,activation = 'softmax')(x) #返回输出值 return outputs #定义B模型架构 #13 weight layers #对于其他网络,与前一网络重合部分沿用前一网络权重,其他网络层权重用正态分布进行初始化,偏置全部初始化为0 def VGG_B(inputs): #第一部分卷积 #Input 224x224x3 #64个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 224x224x64 x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(inputs) x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第一部分池化 #Input 224x224x64 #Output 112x112x64 x = MaxPooling2D()(x) #第二部分卷积 #Input 112x112x64 #128个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 112x112x128 x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第二部分最大池化 #Input 112x112x128 #Output 56x56x128 x = MaxPooling2D()(x) #第三部分卷积 #Input 56x56x128 #Output 56x56x256 x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第三部分最大池化 #Input 56x56x256 #Output 28x28x256 x = MaxPooling2D()(x) #第四部分卷积 #Input 28x28x256 #Output 28x28x512 x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第四部分最大池化 #Input 28x28x512 #Output 14x14x512 x = MaxPooling2D()(x) #第五部分卷积 #Input 14x14x512 #Output 14x14x512 x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第五部分最大池化 #Input 14x14x512 #Output 7x7x512 x = MaxPooling2D()(x) #三个全连接层(其中有添加Flatten层作为数据展平,不过论文中没有写) x = Flatten()(x) x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x) x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x)#前两个全连接层添加系数为5*(10)**(-4)的L2正则化 x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 outputs = Dense(1000,activation = 'softmax')(x) #返回输出值 return outputs #定义C模型架构 #16 weight layers #对于其他网络,与前一网络重合部分沿用前一网络权重,其他网络层权重用正态分布进行初始化,偏置全部初始化为0 def VGG_C(inputs): #第一部分卷积 #Input 224x224x3 #64个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 224x224x64 x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(inputs) x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第一部分池化 #Input 224x224x64 #Output 112x112x64 x = MaxPooling2D()(x) #第二部分卷积 #Input 112x112x64 #128个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 112x112x128 x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第二部分最大池化 #Input 112x112x128 #Output 56x56x128 x = MaxPooling2D()(x) #第三部分卷积 #Input 56x56x128 #Output 56x56x256 x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=256,kernel_size=(1,1),strides=(1,1),activation='relu',padding='same')(x) #第三部分最大池化 #Input 56x56x256 #Output 28x28x256 x = MaxPooling2D()(x) #第四部分卷积 #Input 28x28x256 #Output 28x28x512 x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(1,1),strides=(1,1),activation='relu',padding='same')(x) #第四部分最大池化 #Input 28x28x512 #Output 14x14x512 x = MaxPooling2D()(x) #第五部分卷积 #Input 14x14x512 #Output 14x14x512 #1×1 卷积的参数量 = 输入通道 × 输出通道(再+bias) #parameters = kernel_h × kernel_w × in_channels × out_channels + out_channels (bias) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(1,1),strides=(1,1),activation='relu',padding='same')(x) #第五部分最大池化 #Input 14x14x512 #Output 7x7x512 x = MaxPooling2D()(x) #三个全连接层(其中有添加Flatten层作为数据展平,不过论文中没有写) x = Flatten()(x) x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x) x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x)#前两个全连接层添加系数为5*(10)**(-4)的L2正则化 x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 outputs = Dense(1000,activation = 'softmax')(x) #返回输出值 return outputs #定义D模型架构 #16 weight layers #对于其他网络,与前一网络重合部分沿用前一网络权重,其他网络层权重用正态分布进行初始化,偏置全部初始化为0 def VGG_D(inputs): #第一部分卷积 #Input 224x224x3 #64个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 224x224x64 x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(inputs) x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第一部分池化 #Input 224x224x64 #Output 112x112x64 x = MaxPooling2D()(x) #第二部分卷积 #Input 112x112x64 #128个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 112x112x128 x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第二部分最大池化 #Input 112x112x128 #Output 56x56x128 x = MaxPooling2D()(x) #第三部分卷积 #Input 56x56x128 #Output 56x56x256 x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第三部分最大池化 #Input 56x56x256 #Output 28x28x256 x = MaxPooling2D()(x) #第四部分卷积 #Input 28x28x256 #Output 28x28x512 x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第四部分最大池化 #Input 28x28x512 #Output 14x14x512 x = MaxPooling2D()(x) #第五部分卷积 #Input 14x14x512 #Output 14x14x512 #1×1 卷积的参数量 = 输入通道 × 输出通道(再+bias) #parameters = kernel_h × kernel_w × in_channels × out_channels + out_channels (bias) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第五部分最大池化 #Input 14x14x512 #Output 7x7x512 x = MaxPooling2D()(x) #三个全连接层(其中有添加Flatten层作为数据展平,不过论文中没有写) x = Flatten()(x) x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x) x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x)#前两个全连接层添加系数为5*(10)**(-4)的L2正则化 x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 outputs = Dense(1000,activation = 'softmax')(x) #返回输出值 return outputs #定义E模型架构 #19 weight layers #对于其他网络,与前一网络重合部分沿用前一网络权重,其他网络层权重用正态分布进行初始化,偏置全部初始化为0(权重迁移) def VGG_E(inputs): #第一部分卷积 #Input 224x224x3 #64个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 224x224x64 x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(inputs) x = Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第一部分池化 #Input 224x224x64 #Output 112x112x64 x = MaxPooling2D()(x) #第二部分卷积 #Input 112x112x64 #128个卷积核,卷积核大小3x3,步长为1,激活函数为relu,填充至大小相等 #Output 112x112x128 x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第二部分最大池化 #Input 112x112x128 #Output 56x56x128 x = MaxPooling2D()(x) #第三部分卷积 #Input 56x56x128 #Output 56x56x256 x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第三部分最大池化 #Input 56x56x256 #Output 28x28x256 x = MaxPooling2D()(x) #第四部分卷积 #Input 28x28x256 #Output 28x28x512 x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第四部分最大池化 #Input 28x28x512 #Output 14x14x512 x = MaxPooling2D()(x) #第五部分卷积 #Input 14x14x512 #Output 14x14x512 #1×1 卷积的参数量 = 输入通道 × 输出通道(再+bias) #parameters = kernel_h × kernel_w × in_channels × out_channels + out_channels (bias) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) x = Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')(x) #第五部分最大池化 #Input 14x14x512 #Output 7x7x512 x = MaxPooling2D()(x) #三个全连接层(其中有添加Flatten层作为数据展平,不过论文中没有写) x = Flatten()(x) x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x) x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 x = Dense(4096,activation = 'relu',kernel_regularizer=L2(5*(10)**(-4)))(x)#前两个全连接层添加系数为5*(10)**(-4)的L2正则化 x = Dropout(0.5)(x) # 添加 Dropout 层,丢弃比例为 0.5 outputs = Dense(1000,activation = 'softmax')(x) #返回输出值 return outputs """ 3、训练测试 """ if __name__ == "__main__": # 设置混合精度策略 policy = tf.keras.mixed_precision.Policy('mixed_float16') tf.keras.mixed_precision.set_global_policy(policy) #定义模型架构 #定义输入层 #输入224x224x3的图片,批次为256(batch_size,height,width,channels) inputs = Input(shape=(224,224,3),name='input_layer',batch_size=128) #构建模型vgg_a outputs = VGG_A(inputs) vgg_a = Model(inputs = inputs, outputs = outputs) #小批量梯度下降(SGD小批量随机梯度下降),学习率0.01(10**(-2)),动量下降动量0.9 optimizer = tf.keras.optimizers.SGD(learning_rate=0.01, momentum=0.9)#手动编辑优化器和学习率,后续的网络使用相同的优化器 #编译模型 vgg_a.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy']) #打印模型架构并输出图片 vgg_a.summary() tf.keras.utils.plot_model(vgg_a, to_file='VGG_A.png', show_shapes=True) ''' #构建模型vgg_a_lrn outputs = VGG_A_LRN(inputs) vgg_a_lrn = Model(inputs = inputs, outputs = outputs) #编译模型 vgg_a_lrn.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy']) #打印模型架构并输出图片 vgg_a_lrn.summary() tf.keras.utils.plot_model(vgg_a_lrn, to_file='VGG_A_LRN.png', show_shapes=True) #构建模型vgg_b outputs = VGG_B(inputs) vgg_b = Model(inputs = inputs,outputs = outputs) #编译模型 vgg_b.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy']) #打印模型架构并输出图片 vgg_b.summary() tf.keras.utils.plot_model(vgg_b, to_file='VGG_B.png', show_shapes=True) #构建模型vgg_c outputs = VGG_C(inputs) vgg_c = Model(inputs = inputs,outputs = outputs) #编译模型 vgg_c.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy']) #打印模型架构并输出图片 vgg_c.summary() tf.keras.utils.plot_model(vgg_c, to_file='VGG_C.png', show_shapes=True) #构建模型vgg_d outputs = VGG_D(inputs) vgg_d = Model(inputs = inputs,outputs = outputs) #编译模型 vgg_d.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy']) #打印模型架构并输出图片 vgg_d.summary() tf.keras.utils.plot_model(vgg_d, to_file='VGG_D.png', show_shapes=True) #构建模型vgg_e outputs = VGG_E(inputs) vgg_e = Model(inputs = inputs,outputs = outputs) #编译模型 vgg_e.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy']) #打印模型架构并输出图片 vgg_e.summary() tf.keras.utils.plot_model(vgg_e, to_file='VGG_E.png', show_shapes=True) ''' ''' """ #检查GPU是否有用 import tensorflow as tf print(tf.config.list_physical_devices('GPU')) #自动分配 GPU 内存,TensorFlow 会自动分配 GPU 内存,但可以通过以下代码手动设置: gpus = tf.config.experimental.list_physical_devices('GPU') if gpus: try: for gpu in gpus: tf.config.experimental.set_memory_growth(gpu, True) except RuntimeError as e: print(e) #在训练模型时,TensorFlow 会自动利用 GPU 加速,无需额外设置 #使用混合精度训练,混合精度训练可以进一步加速训练过程并减少内存占用:(混合精度训练是一种在深度学习中常用的加速训练的技术,它结合了单精度浮点数(float32)和半精度浮点数(float16)的优势,以达到更快的训练速度和更低的内存占用,同时尽量减少精度损失。) from tensorflow.keras.mixed_precision import experimental as mixed_precision policy = mixed_precision.Policy('mixed_float16') mixed_precision.set_policy(policy) """ #训练模型 history = model.fit(train_data, epochs=10, batch_size=32, validation_data=val_data) #评估模型 test_loss, test_acc = model.evaluate(test_data) print(f'Test accuracy: {test_acc}') #保存模型 model.save('my_model.h5') # 保存整个模型 model.save_weights('my_model_weights.h5') # 只保存权重 ''' #数据预处理 train_dataset,validation_dataset,test_dataset=loadDataset() # 定义 ReduceLROnPlateau 回调函数 reduce_lr = ReduceLROnPlateau( monitor='val_accuracy', # 监控验证集的准确率 factor=0.1, # 学习率衰减因子 patience=5, # 等待多少个 epoch 后才调整学习率,连续3个epoch学习率没有提高就衰减 min_lr=1e-6, # 学习率的最小值 verbose=1 # 打印详细信息,在调整学习率的时候打印详细信息 ) #在fit中调用回调函数即可在相应监控状态执行 #训练模型 history = vgg_a.fit(train_dataset, epochs=100, validation_data=validation_dataset, callbacks=[reduce_lr] # 添加回调函数 ) #评估模型 test_loss, test_acc = vgg_a.evaluate(test_dataset) print(f'Test accuracy: {test_acc}') #保存模型 vgg_a.save('my_model.h5') # 保存整个模型 #在每次训练或数据加载完成后,清理 TensorFlow 会话可以释放 GPU 内存。这有助于避免内存泄漏和重复分配问题。 tf.keras.backend.clear_session() """ # 计算代码的行数 code_lines = code.split('\n') num_lines = len(code_lines) # 根据代码行数动态调整图像高度 fig_height = max(5, num_lines * 0.18) # 每行代码占用 0.2 英寸,最小高度为 5 英寸 fig, ax = plt.subplots(figsize=(15, fig_height)) # 绘制代码 ax.text(0, 0, code, fontsize=12, ha='left', va='bottom', wrap=True) ax.axis('off') plt.tight_layout() # 保存图片 plt.savefig('code_image.png') plt.close() """ 这我代码"D:\2025College Student Innovation and Entrepreneurship Project\environment\py3.6(tf2.6+cuda11.2+cudnn8.1)\Scripts\python.exe" "D:/2025College Student Innovation and Entrepreneurship Project/project/VGG/VGG.py" 显存动态分配成功! 2025-08-12 18:23:05.473429: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX AVX2 To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags. 2025-08-12 18:23:05.593371: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 5563 MB memory: -> device: 0, name: NVIDIA GeForce RTX 4060 Laptop GPU, pci bus id: 0000:01:00.0, compute capability: 8.9 Model: "model" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_layer (InputLayer) [(128, 224, 224, 3)] 0 _________________________________________________________________ conv2d (Conv2D) (128, 224, 224, 64) 1792 _________________________________________________________________ max_pooling2d (MaxPooling2D) (128, 112, 112, 64) 0 _________________________________________________________________ conv2d_1 (Conv2D) (128, 112, 112, 128) 73856 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (128, 56, 56, 128) 0 _________________________________________________________________ conv2d_2 (Conv2D) (128, 56, 56, 256) 295168 _________________________________________________________________ conv2d_3 (Conv2D) (128, 56, 56, 256) 590080 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (128, 28, 28, 256) 0 _________________________________________________________________ conv2d_4 (Conv2D) (128, 28, 28, 512) 1180160 _________________________________________________________________ conv2d_5 (Conv2D) (128, 28, 28, 512) 2359808 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (128, 14, 14, 512) 0 _________________________________________________________________ conv2d_6 (Conv2D) (128, 14, 14, 512) 2359808 _________________________________________________________________ conv2d_7 (Conv2D) (128, 14, 14, 512) 2359808 _________________________________________________________________ max_pooling2d_4 (MaxPooling2 (128, 7, 7, 512) 0 _________________________________________________________________ flatten (Flatten) (128, 25088) 0 _________________________________________________________________ dense (Dense) (128, 4096) 102764544 _________________________________________________________________ tf.nn.dropout (TFOpLambda) (128, 4096) 0 _________________________________________________________________ dense_1 (Dense) (128, 4096) 16781312 _________________________________________________________________ tf.nn.dropout_1 (TFOpLambda) (128, 4096) 0 _________________________________________________________________ dense_2 (Dense) (128, 1000) 4097000 ================================================================= Total params: 132,863,336 Trainable params: 132,863,336 Non-trainable params: 0 _________________________________________________________________ 2025-08-12 18:23:07.011400: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2) (128, 224, 224, 3) (128,) Epoch 1/100 2025-08-12 18:23:08.311120: I tensorflow/stream_executor/cuda/cuda_dnn.cc:369] Loaded cuDNN version 8600 7/8 [=========================>....] - ETA: 0s - loss: 12.8838 - accuracy: 0.00222025-08-12 18:23:45.369397: W tensorflow/core/framework/op_kernel.cc:1680] Invalid argument: required broadcastable shapes Traceback (most recent call last): File "D:/2025College Student Innovation and Entrepreneurship Project/project/VGG/VGG.py", line 1002, in <module> callbacks=[reduce_lr] # 添加回调函数 File "D:\2025College Student Innovation and Entrepreneurship Project\environment\py3.6(tf2.6+cuda11.2+cudnn8.1)\lib\site-packages\keras\engine\training.py", line 1184, in fit tmp_logs = self.train_function(iterator) File "D:\2025College Student Innovation and Entrepreneurship Project\environment\py3.6(tf2.6+cuda11.2+cudnn8.1)\lib\site-packages\tensorflow\python\eager\def_function.py", line 885, in __call__ result = self._call(*args, **kwds) File "D:\2025College Student Innovation and Entrepreneurship Project\environment\py3.6(tf2.6+cuda11.2+cudnn8.1)\lib\site-packages\tensorflow\python\eager\def_function.py", line 917, in _call return self._stateless_fn(*args, **kwds) # pylint: disable=not-callable File "D:\2025College Student Innovation and Entrepreneurship Project\environment\py3.6(tf2.6+cuda11.2+cudnn8.1)\lib\site-packages\tensorflow\python\eager\function.py", line 3040, in __call__ filtered_flat_args, captured_inputs=graph_function.captured_inputs) # pylint: disable=protected-access File "D:\2025College Student Innovation and Entrepreneurship Project\environment\py3.6(tf2.6+cuda11.2+cudnn8.1)\lib\site-packages\tensorflow\python\eager\function.py", line 1964, in _call_flat ctx, args, cancellation_manager=cancellation_manager)) File "D:\2025College Student Innovation and Entrepreneurship Project\environment\py3.6(tf2.6+cuda11.2+cudnn8.1)\lib\site-packages\tensorflow\python\eager\function.py", line 596, in call ctx=ctx) File "D:\2025College Student Innovation and Entrepreneurship Project\environment\py3.6(tf2.6+cuda11.2+cudnn8.1)\lib\site-packages\tensorflow\python\eager\execute.py", line 60, in quick_execute inputs, attrs, num_outputs) tensorflow.python.framework.errors_impl.InvalidArgumentError: required broadcastable shapes [[node model/tf.nn.dropout/dropout/Mul_1 (defined at /2025College Student Innovation and Entrepreneurship Project/project/VGG/VGG.py:1002) ]] [Op:__inference_train_function_5416] Function call stack: train_function Process finished with exit code 1 以上是报错,由啥问题
08-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值