当前位置: 首页 > news >正文

神经网络小记-优化器

优化器是深度学习中用于优化神经网络模型的一类算法,其主要作用是根据模型的损失函数来调整模型的参数,使得模型能够更好地拟合训练数据,提高模型的性能和泛化能力。优化器在训练过程中通过不断更新模型的参数,使模型逐步接近最优解。

具体来说,优化器的作用包括:

  1. 参数更新:优化器根据损失函数计算出的梯度信息来更新模型的参数,使得模型能够朝着损失函数下降的方向调整,从而最小化损失函数。

  2. 收敛加速:优化器通过引入动量等技术,可以加速模型的收敛过程,从而更快地找到较好的参数组合。

  3. 避免梯度消失或爆炸:在深度神经网络中,由于多层的链式求导可能导致梯度消失或爆炸问题。优化器通过适当的学习率调整和梯度裁剪等技巧,可以缓解这些问题,保证模型的稳定训练。

  4. 自适应调整学习率:一些优化器如Adagrad、RMSprop和Adam等具有自适应学习率的特性,能够根据参数梯度的历史信息动态调整学习率,以适应不同参数的学习速度。

  5. 防止过拟合:优化器通过在训练过程中更新参数,可以在一定程度上防止模型在训练数据上过度拟合,提高模型的泛化能力。

ps:

同一个优化器通常可以用于分类和回归等不同类型的任务。优化器的作用是通过更新模型的参数来最小化损失函数,而损失函数的选择取决于具体的任务类型。

在深度学习中,优化器的选择一般与损失函数的选择是独立的。优化器的目标是最小化损失函数,而不同类型的损失函数对应着不同的任务。

不论是分类还是回归任务,我们都可以使用相同的优化器来最小化相应的损失函数。优化器的选择不依赖于任务类型,而是根据优化效果、收敛速度等因素来进行选择。可以将同一个优化器用于分类和回归等不同类型的任务,但在使用时需要注意选择合适的损失函数来匹配不同的任务类型。

常见的优化器

  1. 随机梯度下降(Stochastic Gradient Descent,SGD):

    • SGD是最基础的优化算法之一,每次迭代从训练数据中随机选择一个样本来计算梯度,并更新模型参数。
    • 优点:计算速度较快,易于实现和理解。
    • 缺点:可能会陷入局部最优点,梯度更新不稳定。
  2. 动量(Momentum):

    • 动量优化器在SGD的基础上加入了动量项,用于加速收敛并减少震荡。
    • 动量可以理解为模拟物体在梯度方向上滚动的速度,有助于在陡峭的损失曲面上更快地前进。
    • 优点:加速收敛,减少震荡。
    • 缺点:可能会在平坦区域陷入局部最优。
  3. 自适应学习率优化器:

    • Adagrad:Adagrad根据参数的历史梯度信息来调整学习率,适用于稀疏数据。
    • RMSprop:RMSprop是对Adagrad的改进版本,通过引入一个衰减系数来防止学习率过快地下降。
    • Adam:Adam是结合了动量和RMSprop的优化器,常用于深度学习中,具有较好的性能和鲁棒性。
    • 优点:自适应调整学习率,对不同参数使用不同的学习率,收敛速度较快。
    • 缺点:需要额外的超参数调优,可能会增加计算开销。
  4. 学习率衰减(Learning Rate Decay):

    • 学习率衰减是一种在训练过程中逐渐减小学习率的技术,以便更好地优化模型。
    • 通过逐步减小学习率,可以在训练初期较快地接近全局最优点,然后逐渐减小学习率以更细致地调整参数。
  5. Nesterov Accelerated Gradient(NAG):

    • NAG是对动量优化器的改进版本,在计算梯度时采用模型参数的更新值,有助于提高优化效率。
    • 通过提前考虑动量项,可以更准确地估计参数更新,提高参数更新的准确性和稳定性。
  6. AdaDelta:

    • AdaDelta是对Adagrad的改进版本,通过动态调整历史梯度信息来避免学习率衰减过快的问题。
    • 不需要手动设置全局学习率,参数更新更加稳定。
  7. AdamW(Adam with Weight Decay):

    • AdamW是对Adam的改进版本,在参数更新时对权重衰减进行更准确的处理,可以提高模型的泛化性能。

每种优化器都有其特点和适用场景。在选择优化器时,应考虑数据集的大小、模型的复杂程度、训练时间和计算资源的限制等因素,并通过实验比较不同优化器的性能,选择最适合当前任务的优化算法。

特点与应用场景

下面是各种优化器的特点和应用场景的简要总结,以表格形式呈现:

优化器特点应用场景
SGD最基础的优化器,全局固定学习率,容易陷入局部最优,收敛较慢。简单问题,数据集较小
Momentum引入动量项,加速收敛,减少震荡,但可能在平坦区域陷入局部最优。大规模数据集,复杂模型
Adagrad自适应学习率,根据参数的历史梯度信息调整学习率,适用于稀疏数据。稀疏数据集,特征稀疏
RMSprop对Adagrad的改进,引入衰减系数,防止学习率过快下降。非平稳数据集,复杂模型
Adadelta对Adagrad的改进,动态调整学习率,避免全局学习率设置。大规模数据集,复杂模型
Adam结合了动量和RMSprop,自适应调整学习率,收敛较快,广泛应用于深度学习。大多数情况下都适用,复杂模型
AdamW在Adam的基础上加入权重衰减,提高模型的泛化性能。大规模数据集,复杂模型
Nadam在Adam的基础上加入Nesterov Accelerated Gradient,动态调整学习率,收敛更快。大规模数据集,复杂模型
L-BFGS二次优化方法,基于拟牛顿法,适用于小数据集和小规模模型。小数据集,小规模模型

torch中常见优化器

  1. SGD(随机梯度下降)
import torch.optim as optimoptimizer = optim.SGD(model.parameters(), lr=learning_rate)
  1. Adam(自适应矩估计)
import torch.optim as optimoptimizer = optim.Adam(model.parameters(), lr=learning_rate)
  1. RMSprop(均方根传递)
import torch.optim as optimoptimizer = optim.RMSprop(model.parameters(), lr=learning_rate)
  1. Adagrad(自适应学习率方法)
import torch.optim as optimoptimizer = optim.Adagrad(model.parameters(), lr=learning_rate)
  1. Adadelta
import torch.optim as optimoptimizer = optim.Adadelta(model.parameters(), lr=learning_rate)
  1. AdamW(带权重衰减的Adam)
import torch.optim as optimoptimizer = optim.AdamW(model.parameters(), lr=learning_rate)

以上示例中,model.parameters()是用于优化的模型参数,lr是学习率(learning rate),它是优化器的一个重要超参数。可以根据具体任务和数据选择合适的优化器及超参数来进行模型训练和优化。

简单神经网络示例

神经网络一般流程:

  1. 前向传播:输入数据通过网络的一系列层,逐层进行线性变换和激活函数处理,得到最终的输出。

  2. 损失函数:根据模型的输出和真实标签计算损失,用于衡量模型的预测与真实值之间的差异。

  3. 反向传播:通过计算损失函数对模型参数的梯度,将梯度从输出层向输入层传播,用于更新网络参数。

  4. 优化器优化器根据反向传播得到的梯度信息,以一定的优化算法来更新神经网络的参数,从而最小化损失函数。

  5. 参数更新:根据优化器计算得到的参数梯度,更新神经网络的权重和偏置,以使模型逐渐收敛于更优的状态。

  6. 迭代训练:通过多次迭代前向传播、反向传播和参数更新,使得神经网络在训练集上逐步调整参数,提高模型性能。

重点讲一下优化器:

  • 优化器:优化器是神经网络训练中的重要组成部分,它决定了参数如何根据损失函数的梯度进行更新,从而使得模型逐步优化。

  • 梯度下降:梯度下降是优化器最基本的思想,根据损失函数的梯度方向,对参数进行更新。其中,SGD(随机梯度下降)是最简单的梯度下降方法,但在训练过程中可能会出现震荡和收敛较慢的问题。

  • 优化算法:为了解决梯度下降的问题,出现了多种优化算法。常见的优化器包括:Momentum、Adagrad、RMSprop、Adam等。这些优化算法在梯度下降的基础上引入了动量、学习率调整等机制,以加速收敛和提高优化效果。

  • 超参数调整:优化器有一些重要的超参数,如学习率、动量等。合理选择这些超参数对模型的性能影响很大。通常需要进行超参数调优来找到最优的参数组合。

  • 稳定性与泛化:优化器的选择和超参数的设置对于神经网络的稳定性和泛化性能有很大影响。不同的优化器和超参数组合可能会导致模型陷入局部最优或过拟合。

  • 自适应学习率:近年来,自适应学习率的优化算法变得流行,如Adagrad、RMSprop和Adam。这些算法可以根据参数的历史梯度信息自适应地调整学习率,从而更有效地进行参数更新。

  • 收敛性:优化器的选择也会影响神经网络是否能够达到较好的收敛性,即在合理的迭代次数内,模型能够趋于稳定状态,同时避免过度拟合。因此,在选择优化器时,需要考虑网络结构、数据集规模和训练策略。

在PyTorch中搭建神经网络和选择优化器的重点步骤如下:

  1. 定义神经网络模型:首先需要定义神经网络模型的结构。可以使用torch.nn.Module来创建一个自定义的神经网络类,并在其构造函数__init__中定义各层和参数。
import torch
import torch.nn as nnclass MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()self.fc1 = nn.Linear(in_features, hidden_size)self.fc2 = nn.Linear(hidden_size, out_features)# 定义其他层...def forward(self, x):x = self.fc1(x)x = torch.relu(x)x = self.fc2(x)return x
  1. 实例化模型和损失函数:在使用模型之前,需要实例化模型,并选择适当的损失函数。同时,需要定义超参数,如学习率(lr)、权重衰减(weight decay)等。
# 实例化模型
model = MyModel()# 定义损失函数
criterion = nn.CrossEntropyLoss()# 定义优化器(标注重点)
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate, weight_decay=weight_decay)
  1. 训练循环:在训练过程中,重点是优化器的使用。在每次迭代中,需要先将梯度清零,然后计算模型输出和损失,接着反向传播计算梯度,并最终通过优化器来更新模型参数。
# 训练循环
for epoch in range(num_epochs):for inputs, labels in dataloader:# 将梯度清零optimizer.zero_grad()# 前向传播outputs = model(inputs)loss = criterion(outputs, labels)# 反向传播loss.backward()# 更新模型参数(优化器的重点操作)optimizer.step()
  1. 验证或测试:在训练后,可以对模型进行验证或测试。在验证或测试阶段,通常不需要进行梯度计算,因此可以使用torch.no_grad()上下文管理器来关闭梯度计算,从而节省内存和计算资源。
# 验证或测试循环
with torch.no_grad():for inputs, labels in val_dataloader:# 前向传播(无需计算梯度)outputs = model(inputs)# 其他验证或测试操作...

以上是在PyTorch中搭建神经网络和标注优化器的主要步骤。选择合适的优化器和设置合理的超参数是训练神经网络的关键。根据任务的复杂度和数据量,可能需要进行不同优化器的尝试和超参数调整。

相关文章:

神经网络小记-优化器

优化器是深度学习中用于优化神经网络模型的一类算法,其主要作用是根据模型的损失函数来调整模型的参数,使得模型能够更好地拟合训练数据,提高模型的性能和泛化能力。优化器在训练过程中通过不断更新模型的参数,使模型逐步接近最优…...

200+行代码写一个简易的Qt界面贪吃蛇

照例先演示一下: 一个简单的Qt贪吃蛇,所有的图片都是我自己画的(得意)。 大致的运行逻辑和之前那个200行写一个C小黑窗贪吃蛇差不多,因此在写这个项目的时候,大多情况是在想怎么通过Qt给展现出来。 背景图…...

redis中使用bloomfilter的白名单功能解决缓存穿透问题

一 缓存预热 1.1 缓存预热 将需要的数据提前缓存到缓存redis中,可以在服务启动时候,或者在使用前一天完成数据的同步等操作。保证后续能够正常使用。 1.2 缓存穿透 在redis中,查询redis缓存数据没有内容,接着查询mysql数据库&…...

Spring Boot 2.7.8以后mysql-connector-java与mysql-connector-j

错误信息 如果升级到Spring Boot 2.7.8&#xff0c;可以看到因为找不到mysql-connector-java依赖而出现错误。 配置&#xff1a; <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId>&l…...

03|「如何写好一个 Prompt」

前言 Prompt 文章目录 前言一、通用模板和范式1. 组成2. 要求1&#xff09;文字描述2&#xff09;注意标点符号 一、通用模板和范式 1. 组成 指令&#xff08;角色&#xff09; 生成主体 额外要求 指令&#xff1a;模型具体完成的任务描述。例如&#xff0c;翻译一段文字&…...

关于提示词 Prompt

Prompt原则 原则1 提供清晰明确的指示 注意在提示词中添加正确的分割符号 prompt """ 请给出下面文本的摘要&#xff1a; <你的文本> """可以指定输出格式&#xff0c;如&#xff1a;Json、HTML提示词中可以提供少量实例&#xff0c;…...

【Linux多线程】线程的互斥与同步(附抢票案例代码+讲解)

线程的互斥与同步 &#x1f4ab; 概念引入⭐️临界资源&#xff08;Critical Resource&#xff09;&#xff1a;&#x1f31f;临界区&#xff08;Critical Section&#xff09;&#xff1a;✨互斥&#xff08;Mutex&#xff09;&#xff1a; ⚡️结合代码看互斥☄️ 代码逻辑&a…...

ajax概述

目录 1.什么是ajax 2.ja原生ajax 3.jQuery框架的ajax 4.综合案例 1.什么是ajax Ajax 即"Asynchronous Javascript And XML"&#xff08;异步 JavaScript 和 XML&#xff09;&#xff0c;是指一种创建交互式网页应用的网页开发技术。Ajax 异步 JavaScript 和 XML&…...

小白带你学习linux的mysql服务(主从mysql服务和读写分离三十一)

目录 二、MySQL Replication优点&#xff1a; 三、MySQL复制类型 1、异步复制&#xff08;Asynchronous repication&#xff09; 2、全同步复制&#xff08;Fully synchronous replication&#xff09; 3、半同步复制&#xff08;Semisynchronous replication&#xff09;…...

【低代码专题方案】iPaaS运维方案,助力企业集成平台智能化高效运维

01 场景背景 随着IT行业的发展和各家企业IT建设的需要&#xff0c;信息系统移动化、社交化、大数据、系统互联、数据打通等需求不断增多&#xff0c;企业集成平台占据各个企业领域&#xff0c;成为各业务系统数据传输的中枢。 集成平台承接的业务系统越多&#xff0c;集成平台…...

Android SDK 上手指南||第一章 环境需求||第二章 IDE:Eclipse速览

第一章 环境需求 这是我们系列教程的第一篇&#xff0c;让我们来安装Android的开发环境并且把Android SDK运行起来&#xff01; 介绍 欢迎来到Android SDK入门指南系列文章&#xff0c;如果你想开始开发Android App&#xff0c;这个系列将从头开始教你所须的技能。我们假定你…...

Amazon Linux上使用ec2-user来设置开机自启动的shell脚本

要在Amazon Linux上使用ec2-user来设置开机自启动的shell脚本&#xff0c;可以按照以下步骤操作&#xff1a; 1. 确保您拥有要设置自启动的shell脚本。假设脚本的路径是/home/ec2-user/myscript.sh。 2. 使用以下命令打开/etc/rc.d/rc.local文件&#xff1a; shell sudo nano /…...

【Spring】Spring 下载及其 jar 包

根据 【动力节点】最新Spring框架教程&#xff0c;全网首套Spring6教程&#xff0c;跟老杜从零学spring入门到高级 以及老杜的原版笔记 https://www.yuque.com/docs/share/866abad4-7106-45e7-afcd-245a733b073f?# 《Spring6》 进行整理&#xff0c; 文档密码&#xff1a;mg9b…...

蓝桥杯2023年第十四届省赛-飞机降落

题目描述 N 架飞机准备降落到某个只有一条跑道的机场。其中第 i 架飞机在 Ti 时刻到达机场上空&#xff0c;到达时它的剩余油料还可以继续盘旋 Di 个单位时间&#xff0c;即它最早 可以于 Ti 时刻开始降落&#xff0c;最晚可以于 Ti Di 时刻开始降落。降落过程需要 Li个单位时…...

STM32 串口实验(学习一)

本章将实现如下功能&#xff1a;STM32通过串口和上位机对话&#xff0c;STM32在收到上位机发过来的字符串后&#xff0c;原原本本返回给上位机。 STM32 串口简介 串口作为MCU的重要外部接口&#xff0c;同时也是软件开发重要的调试手段&#xff0c;其重要性不言而喻。现在基本…...

多臂治疗规则的 Qini 曲线(Stefan Wager)

英文题目&#xff1a; Qini Curves for Multi-Armed Treatment Rules 中文题目&#xff1a;多臂治疗规则的 Qini 曲线 单位&#xff1a;Stefan Wager 论文链接&#xff1a; 代码&#xff1a;GitHub - grf-labs/maq: Treatment rule evaluation via the multi-armed Qini …...

NOSQL之Redis配置及优化

目录 一、关系型数据库 二、非关系型数据库 三、关系型数据库和非关系型数据库区别 1、数据存储方式不同 2、扩展方式不同 3、对事务性的支持不同 四、Redis简介 五、Redis优点 &#xff08;1&#xff09;具有极高的数据读写速度 &#xff08;2&#xff09;支持丰富的…...

植物一区HR | 植物生理组+转录组:揭示豆科植物响应干旱胁迫机制

PlantArray 植物高通量生理学表型监测系统 是一套以植物生理学为基础的高精度&#xff0c;高通量&#xff0c;自动化表型监测系统&#xff0c;集合实验设置、数据分析、决策工具于一身&#xff0c;能够高通量实时动态监测并进行全天候生理及环境参数采集&#xff0c;是进行植物…...

TCP粘包问题

TCP粘包问题 TCP粘包问题造成TCP粘包的原因发送方原因接收方原因 如何处理TCP粘包发送方接收方应用层 为什么UDP没有粘包问题 TCP粘包问题 TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包&#xff0c;从接收缓冲区来看&#xff0c;后一包数据的头紧接着前一包数据…...

QT【day1】

登录框&#xff1a; #include "mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {//窗口设置this->setFixedSize(600,600); //大小this->setWindowTitle("MUMU"); //文本内容this->setWindowOpacity(0.8); //透…...

【Golang】Golang进阶系列教程--为什么 Go 不支持 []T 转换为 []interface

文章目录 前言官方解释内存布局程序运行中的内存布局通用方法 前言 在 Go 中&#xff0c;如果 interface{} 作为函数参数的话&#xff0c;是可以传任意参数的&#xff0c;然后通过类型断言来转换。 举个例子&#xff1a; package mainimport "fmt"func foo(v inter…...

两数相加 II——力扣445

题目描述 法一 栈 本题旨在从后往前加&#xff0c;为了逆序处理所有数位&#xff0c;利用栈&#xff0c;把数字压入栈中&#xff0c;再依次取出相加&#xff0c;注意进位&#xff01;进位是/10&#xff0c;另外需要注意栈的常用函数&#xff0c;push()、pop()、top()&#xff0…...

js获取上传视频的封面第一帧

代码如下&#xff1a;粘贴到这个在线编辑器里&#xff0c;可以测试效果。 菜鸟教程在线编辑器 <div><div style"flex: 1;border: 1px solid #999; position:relative;color: #333;background-color:#FFF2B8;"><span style"position: absolute…...

Nginx 高可用负载均衡(三种模式)

一、nginx普通集群负载均衡 1、安装keepalived (1)下载 https://www.keepalived.org/download.html(2)解压 tar -zxvf keepalived-2.0.18.tar.gz(3)使用configure命令配置安装目录与核心配置文件所在位置&#xff1a; ./configure --prefix/usr/local/keepalived --sysconf/e…...

Linux tail命令

在Linux中&#xff0c;tail命令用于查看文件的末尾内容。它可以显示文件的最后几行&#xff0c;默认情况下显示最后10行。 以下是一些常见的使用方式和示例&#xff1a; 显示文件的最后10行&#xff1a; tail filename将会显示名为filename的文件的最后10行内容。 显示文件…...

【屏幕适配发展介绍 Objective-C语言】

一、接下来,我们花一天时间,给大家介绍这个屏幕适配 1.那么,屏幕适配,是什么意思啊 我们说,写程序的时候,我们有时候要做 1)系统适配 2)屏幕适配 1)系统适配:是指的你写的这个代码,在iOS6、iOS7、iOS8,在不同的iOS系统下,是不是运行的效果,一致吧 这个指的是…...

linux中ls命令详解

ls 显示目录内容列表 补充说明 ls命令 就是list的缩写&#xff0c;用来显示目标列表&#xff0c;在Linux中是使用率较高的命令。ls命令的输出信息可以进行彩色加亮显示&#xff0c;以分区不同类型的文件。 语法 ls [选项] [文件名...][-1abcdfgiklmnopqrstuxABCDFGLNQRSUX…...

大盗阿福(记忆化搜索板子)

提供核心代码&#xff1a;&#xff08;经典的记忆化搜索套路&#xff09; int dfs(int pos){if(f[pos]!-1) return f[pos];//记忆化if(pos>n) return 0;//边界&#xff0c;越界int sum0;//模板int f10,f20;f1dfs(pos1);f2dfs(pos2)w[pos];summax(f1,f2);//模板f[pos]sum;//模…...

打卡力扣题目八

#左耳听风 ARST 打卡活动重启# 目录 一、问题 二、解题方法一 三、解题方法二 四、两种方法的区别 关于 ARTS 的释义 —— 每周完成一个 ARTS&#xff1a; ● Algorithm: 每周至少做一个 LeetCode 的算法题 ● Review: 阅读并点评至少一篇英文技术文章 ● Tips: 学习至少一…...

matlab使用教程(5)—矩阵定义和基本运算

本博客介绍如何在 MATLAB 中创建矩阵和执行基本矩阵计算。 MATLAB 环境使用矩阵来表示包含以二维网格排列的实数或复数的变量。更广泛而言&#xff0c;数组为向量、矩阵或更高维度的数值网格。MATLAB 中的所有数组都是矩形&#xff0c;在这种意义上沿任何维度的分量向量的长度…...

wordpress自定义登录/网站维护一般都是维护什么

安徽新华学院《局域网组建、管理与维护》的评分标准相关搜索: 安徽, 局域网, 新华, 评分, 学院安徽新华学院2009-2010学年度第一学期《局域网组建、管理与维护》期末考试参考答案及评分标准&#xff08;A卷,考核&#xff09;命题教师 应作斌 审核人&#xff1a; 适用年级…...

桂林北站疫情防控最新消息/seo排名优化表格工具

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2022高压电工复审题库为高压电工模拟考试题库考前必练习题目&#xff01;2022高压电工理论题库及在线模拟考试根据高压电工新版教材大纲编写。高压电工模拟考试试题随时根据安全生产模拟考试一点通上查找答案。 1、【…...

珠江新城网站建设/百度学术官网首页

转载自 天平 博客 http://blog.csdn.net/niubitianping/article/details/52624417 问题 1. error: Failed to start an Appium session, err was: Error: Requested a new session but one was in progress 之前的会话没有关闭&#xff0c;然后你又运行了测试实例&#xff0c…...

网站开发一般用什么工具/外贸seo推广公司

https://www.huaweicloud.com/articles/992cce27083f08de34006f20d4336fae.html 线程的安全机制——读写锁 读写锁 读写锁API pthread_rwlock_init 初始化读写锁 pthread_rwlock_destroy 销毁读写锁 pthread_rwlock_rdlock 上读锁 pthread_rwlock_wrlock 上写锁 pth…...

企业网站文章后台添加/优化大师免费安装下载

1.阿里巴巴矢量图官网&#xff1a;https://www.iconfont.cn/ 2.把需要用到的图标加入购物车&#xff0c;需要注册登录 3.把选好的图标添加至项目 4.下载到本地 5.解压&#xff0c;打开&#xff0c;选择复制这四个文件&#xff0c;粘贴到项目的css文件里 6.在项目中使用...

wordpress 繁体/营销方式和营销策略

关于事件 在我们使用javascript开发时&#xff0c;我们会经常用到很多事件&#xff0c;如点击、键盘、鼠标等等&#xff0c;这些物理性的事件。而我们今天所说的我称之为事件的&#xff0c;是另一种形式的事件&#xff0c;订阅---发布&#xff0c;又叫做观察者模式&#xff0c;…...