【LLM第二篇】stable diffusion扩散模型、名词解释

最近在整理大模型的相关资料,发现了几个名词,不是很懂,这里整理一下:

stable diffusion(SD)模型:

扩散模型(Diffusion model)的一种,主要用于生成高质量的图像,GAN的替代者,扩散模型通过一些列学习步骤生成数据,逐渐从噪声中生成目标图像。

主要原理:

扩散模型主要分成两个阶段:前向过程(forward process) 和反向过程(reverse process)

1.前向过程(noise adding process):在这个过程中,模型逐步将高质量的图像添加噪声,直到图像完全变成噪声。这是一个可控的Markov链过程,也就是说图像经过一定数量的时间步骤后变成了纯噪声数据。

2.反向过程(noise removing process):反向过程即为生成过程。在这个阶段,模型学习如何将前向过程中得到的噪声数据逆向转化为清晰的图像,通过神经网络的训练,学习从噪声中移除噪声并恢复出原始图像。

要解决的问题:

扩散模型,包括stable diffusion模型,旨在解决如何生成高质量、高分辨率、具有多样性的图像问题。与传统的GAN相比,扩散模型通常能够更好的处理图像的细节,并在训练时更加稳定。

扩散模型不需要使用对抗性训练,而是依赖变分下降路径(variational lower bound),使得模型在训练过程中更加稳定,扩散模型的优势是可以避免GAN的一些模式崩溃(mode collapse)、训练不稳定的问题。

总的来说,扩散模型通过模仿如何将数据转化成噪声和如何从噪声中恢复数据的过程,以一种稳定而有效的方式生成质量高的图像。在艺术创作、游戏开发、数据增强等多个领域有潜在的应用价值。

Stable Diffusion出现之前的扩散模型虽然已经有非常强的生成能力与泛化性能,但缺点是不管是前向扩散过程还是反向扩散过程,都需要在像素级的图像上进行,当图像分辨率和Timesteps很大时,不管是训练还是前向推理,都非常的耗时

而基于Latent的扩散模型可以将这些过程压缩在低维的Latent隐空间,这样一来大大降低了显存占用和计算复杂度,这是常规扩散模型和基于Latent的扩散模型之间的主要区别,也是SD模型火爆出圈的关键一招

举个形象的例子理解一下,如果SD模型将输入数据压缩的倍数设为8,那么原本尺寸为[3,512,512]的数据就会进入[3,64,64]的Latent隐空间中,显存和计算量直接缩小64倍,整体效率大大提升。也正是因为这样,SD模型能够在2080Ti级别的显卡上进行前向推理,生成各种各样精美的图像,大大推动了SD模型的普惠与AI绘画生态的繁荣

Stable Diffusion整体的训练逻辑也非常清晰:

  1. 从数据集中随机选择一个训练样本
  2. 从K个噪声量级随机抽样一个timestep 
  3. 将timestep 对应的高斯噪声添加到图片中
  4. 将加噪图片输入U-Net中预测噪声
  5. 计算真实噪声和预测噪声的L2损失
  6. 计算梯度并更新SD模型参数

【1】SD训练集加入噪声

SD模型训练时,我们需要把加噪的数据集输入模型中,每一次迭代我们用random函数生成从强到弱各个强度的噪声,通常来说会生成0-1000一共1001种不同的噪声强度,通过Time Embedding嵌入到SD的训练过程中。

Time Embedding由Timesteps(时间步长)编码而来,引入Timesteps能够模拟一个随时间逐渐向图像加入噪声扰动的过程。每个Timestep代表一个噪声强度(较小的Timestep代表较弱的噪声扰动,而较大的Timestep代表较强的噪声扰动),通过多次增加噪声来逐渐改变干净图像的特征分布。

【2】SD训练中加噪与去噪

具体地,在训练过程中,我们首先看一下前向扩散过程,主要是对干净样本进行加噪处理,采用多次逐步增加噪声的方式,直至干净样本转变成为纯噪声。

接着,在前向扩散过程进行的每一步中,SD同样进行反向扩散过程。SD模型在每一步都会预测当前步加入的噪声,不断学习提升去噪能力。

其中,将去噪过程具像化,就得到使用U-Net预测噪声,并结合Schedule算法逐步去噪的过程

以看到,加噪和去噪过程都是逐步进行的,我们假设进行�步,那么每一步,SD都要去预测噪声,从而形成“小步快跑的稳定去噪”,类似于移动互联网时代的产品逻辑,这是足够伟大的关键一招

与此同时,在加噪过程中,每次增加的噪声量级可以不同,假设有5种噪声量级,那么每次都可以取一种量级的噪声,增加噪声的多样性,如下图所示:

多量级噪声

那么怎么让网络知道目前处于的哪一步呢?本来SD模型其实需要K个噪声预测模型,这时我们可以增加一个Time Embedding(类似Positional embeddings)进行处理,通过将timestep编码进网络中,从而只需要训练一个共享的U-Net模型,就让网络知道现在处于哪一步。

我们希望SD中的U-Net模型在刚开始的反向扩散过程中可以先生成一些物体的大体轮廓,随着反向扩散过程的深入,在即将完成完整图像的生成时,再生成一些高频的特征信息。

我们了解了训练中的加噪和去噪过程,SD训练的具体过程就是对每个加噪和去噪过程进行梯度计算,从而优化SD模型参数,如下图所示分为四个步骤:

  1. 从训练集中选取一张加噪过的图片和噪声强度(timestep),然后将其输入到U-Net中。
  2. 让U-Net预测噪声(下图中的U-Net Prediction)。
  3. 接着再计算预测噪声与真实噪声的误差(loss)。
  4. 最后通过反向传播更新U-Net的权重参数。

【3】文本信息对图片生成的控制

SD模型在生成图片时,需要输入prompt提示词,那么这些文本信息是如何影响图片的生成呢?

答案非常简单:通过注意力机制。

在SD模型的训练中,每个训练样本都会对应一个文本描述的标签,我们将对应标签通过CLIP Text Encoder输出Text Embeddings,并将Text Embeddings以Cross Attention的形式与U-Net结构耦合并注入,使得每次输入的图片信息与文本信息进行融合训练,如下图所示:

Noise与Text Embeddings通过CrossAttention与U-Net结构耦合

【4】SD模型训练时的输入

有了上面的介绍,我们在这里可以小结一下SD模型训练时的输入,一共有三个部分组成:图片、文本以及噪声强度。其中图片和文本是固定的,而噪声强度在每一次训练参数更新时都会随机选择一个进行叠加。

U-net模型

【1】Stable Diffusion中U-Net的核心作用

在Stable Diffusion中,U-Net模型是一个关键核心部分,能够预测噪声残差,并结合Sampling method(调度算法:PNDM,DDIM,K-LMS等)对输入的特征矩阵进行重构,逐步将其从随机高斯噪声转化成图片的Latent Feature

具体来说,在前向推理过程中,SD模型通过反复调用 U-Net,将预测出的噪声残差从原噪声矩阵中去除,得到逐步去噪后的图像Latent Feature,再通过VAE的Decoder结构将Latent Feature重建成像素级图像

【2】Stable Diffusion中U-Net模型的完整结构图

Stable Diffusion中的U-Net,在传统深度学习时代的Encoder-Decoder结构的基础上,增加了ResNetBlock(包含Time Embedding)模块,Spatial Transformer(SelfAttention + CrossAttention + FeedForward)模块以及CrossAttnDownBlock,CrossAttnUpBlock和CrossAttnMidBlock模块

那么各个模块都有什么作用呢?不着急,咱们先看看SD U-Net的整体架构(AIGC算法工程师面试核心考点)。

下图是Stable Diffusion U-Net的完整结构图,大家可以感受一下其魅力,看着这个完整结构图学习Stable Diffusion U-Net部分,相信大家脑海中的思路也会更加清晰:

上图中包含Stable Diffusion U-Net的十四个基本模块:

  1. GSC模块:Stable Diffusion U-Net中的最小组件之一,由GroupNorm+SiLU+Conv三者组成。
  2. DownSample模块:Stable Diffusion U-Net中的下采样组件,使用了Conv(kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))进行采下采样
  3. UpSample模块:Stable Diffusion U-Net中的上采样组件,由插值算法(nearest)+Conv组成。
  4. ResNetBlock模块:借鉴ResNet模型的“残差结构”,让网络能够构建的更深的同时,将Time Embedding信息嵌入模型
  5. CrossAttention模块:将文本的语义信息与图像的语义信息进行Attention机制,增强输入文本Prompt对生成图片的控制。
  6. SelfAttention模块:SelfAttention模块的整体结构与CrossAttention模块相同,这是输入全部都是图像信息,不再输入文本信息。
  7. FeedForward模块:Attention机制中的经典模块,由GeGlU+Dropout+Linear组成。
  8. BasicTransformer Block模块:由LayerNorm+SelfAttention+CrossAttention+FeedForward组成,是多重Attention机制的级联,并且也借鉴ResNet模型的“残差结构”。通过加深网络和多Attention机制,大幅增强模型的学习能力与图文的匹配能力
  9. Spatial Transformer模块:由GroupNorm+Conv+BasicTransformer Block+Conv构成,ResNet模型的“残差结构”依旧没有缺席。
  10. DownBlock模块:由两个ResNetBlock模块组成。
  11. UpBlock_X模块:由X个ResNetBlock模块和一个UpSample模块组成。
  12. CrossAttnDownBlock_X模块:是Stable Diffusion U-Net中Encoder部分的主要模块,由X个(ResNetBlock模块+Spatial Transformer模块)+DownSample模块组成。
  13. CrossAttnUpBlock_X模块:是Stable Diffusion U-Net中Decoder部分的主要模块,由X个(ResNetBlock模块+Spatial Transformer模块)+UpSample模块组成。
  14. CrossAttnMidBlock模块:是Stable Diffusion U-Net中Encoder和ecoder连接的部分,由ResNetBlock+Spatial Transformer+ResNetBlock组成。

为大家全面分析SD模型中U-Net结构的核心知识

(1)ResNetBlock模块

在传统深度学习时代,ResNet的残差结构在图像分类,图像分割,目标检测等主流方向中几乎是不可或缺,其简洁稳定有效的“残差思想”终于在AIGC时代跨过周期,在SD模型的U-Net结构中继续繁荣

值得注意的是,Time Embedding正是输入到ResNetBlock模块中,为U-Net引入了时间信息(时间步长T,T的大小代表了噪声扰动的强度),模拟一个随时间变化不断增加不同强度噪声扰动的过程,让SD模型能够更好地理解时间相关性

同时,在SD模型调用U-Net重复迭代去噪的过程中,我们希望在迭代的早期,能够先生成整幅图片的轮廓与边缘特征,随着迭代的深入,再补充生成图片的高频和细节特征信息。由于在每个ResNetBlock模块中都有Time Embedding,就能告诉U-Net现在是整个迭代过程的哪一步,并及时控制U-Net够根据不同的输入特征和迭代阶段而预测不同的噪声残差

在上面的Stable Diffusion U-Net完整结构图中展示了完整的ResNetBlock模块,其输入包括Latent Feature和 Time Embedding。首先Latent Feature经过GSC(GroupNorm+SiLU激活函数+卷积)模块后和Time Embedding(经过SiLU激活函数+全连接层处理)做加和操作,之后再经过GSC模块和Skip Connection而来的输入Latent Feature做加和操作,进行两次特征融合后最终得到ResNetBlock模块的Latent Feature输出,增强SD模型的特征学习能力

同时,和传统深度学习时代的U-Net结构一样,Decoder结构中的ResNetBlock模块不单单要接受来自上一层的Latent Feature,还要与Encoder结构中对应层的ResNetBlock模块的输出Latent Feature进行concat操作。举个例子,如果Decoder结构中ResNetBlock Structure上一层的输出结果的尺寸为 [512, 512, 1024],Encoder结构对应 ResNetBlock Structure的输出结果的尺寸为 [512, 512, 2048],那么这个Decoder结构中ResNeBlock Structure得到的Latent Feature的尺寸为 [512, 512, 3072]。

(2)CrossAttention模块

CrossAttention模块是我们使用输入文本Prompt控制SD模型图片内容生成的关键一招。

上面的Stable Diffusion U-Net完整结构图中展示了Spatial Transformer(Cross Attention)模块的结构。Spatial Transformer模块和ResNetBlock模块一样接受两个输入:一个是ResNetBlock模块的输出,另外一个是输入文本Prompt经过CLIP Text Encoder模型编码后的Context Embedding。

两个输入首先经过Attention机制(将Context Embedding对应的语义信息与图片中对应的语义信息相耦合),输出新的Latent Feature,再将新输出的Latent Feature与输入的Context Embedding再做一次Attention机制,从而使得SD模型学习到了文本与图片之间的特征对应关系

Spatial Transformer模块不改变输入输出的尺寸,只在图片对应的位置上融合了语义信息,所以不管是在传统深度学习时代,还是AIGC时代,Spatial Transformer都是将本文与图像结合的一个“万金油”模块

看CrossAttention模块的结构图,大家可能会疑惑为什么Context Embedding用来生成K和V,Latent Feature用来生成Q呢?

原因也非常简单:因为在Stable Diffusion中,主要的目的是想把文本信息注入到图像信息中里,所以用图片token对文本信息做 Attention实现逐步的文本特征提取和耦合。

3)BasicTransformer Block模块

BasicTransformer Block模块是在CrossAttention子模块的基础上,增加了SelfAttention子模块和Feedforward子模块共同组成的,并且每个子模块都是一个残差结构,这样除了能让文本的语义信息与图像的语义信息更好的融合之外,还能通过SelfAttention机制让模型更好的学习图像数据的特征

写到这里,可能还有读者会问,Stable Diffusion U-Net中的SelfAttention到底起了什么作用呀?

首先,在Stable Diffusion U-Net的SelfAttention模块中,输入只有图像信息,所以SelfAttention主要是为了让SD模型更好的学习图像数据的整体特征

再者,SelfAttention可以将输入图像的不同部分(像素或图像Patch)进行交互,从而实现特征的整合和全局上下文的引入,能够让模型建立捕捉图像全局关系的能力,有助于模型理解不同位置的像素之间的依赖关系,以更好地理解图像的语义。

在此基础上,SelfAttention还能减少平移不变性问题,SelfAttention模块可以在不考虑位置的情况下捕捉特征之间的关系,因此具有一定的平移不变性。

(4)Spatial Transformer模块

更进一步的,在BasicTransformer Block模块基础上,加入GroupNorm和两个卷积层就组成Spatial Transformer模块。Spatial Transformer模块是SD U-Net中的核心Base结构,Encoder中的CrossAttnDownBlock模块,Decoder中的CrossAttnUpBlock模块以及CrossAttnMidBlock模块都包含了大量的Spatial Transformer子模块。

在生成式模型中,GroupNorm的效果一般会比BatchNorm更好,生成式模型通常比较复杂,因此需要更稳定和适应性强的归一化方法。

而GroupNorm主要有以下一些优势,让其能够成为生成式模型的标配:

1. 对训练中不同Batch-Size的适应性:在生成式模型中,通常需要使用不同的Batch-Size进行训练和微调。这会导致 BatchNorm在训练期间的不稳定性,而GroupNorm不受Batch-Size的影响,因此更适合生成式模型。

2. 能适应通道数变化:GroupNorm 是一种基于通道分组的归一化方法,更适应通道数的变化,而不需要大量调整。

3. 更稳定的训练:生成式模型的训练通常更具挑战性,存在训练不稳定性的问题。GroupNorm可以减轻训练过程中的梯度问题,有助于更稳定的收敛。

4. 能适应不同数据分布:生成式模型通常需要处理多模态数据分布,GroupNorm 能够更好地适应不同的数据分布,因为它不像 Batch Normalization那样依赖于整个批量的统计信息。

(5)CrossAttnDownBlock/CrossAttnUpBlock/CrossAttnMidBlock模块

在Stable Diffusion U-Net的Encoder部分中,使用了三个CrossAttnDownBlock模块,其由ResNetBlock Structure+BasicTransformer Block+Downsample构成。Downsample通过使用一个卷积(kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))来实现。

在Decoder部分中,使用了三个CrossAttnUpBlock模块,其由ResNetBlock Structure+BasicTransformer Block+Upsample构成。Upsample使用插值算法+卷积来实现,插值算法将输入的Latent Feature尺寸扩大一倍,同时通过一个卷积(kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))改变Latent Feature的通道数,以便于输入后续的模块中。

在CrossAttnMidBlock模块中,包含ResNetBlock Structure+BasicTransformer Block+ResNetBlock Structure,作为U-Net的Encoder与Decoder之间的媒介。

(6)Stable Diffusion U-Net整体宏观角度小结

从整体上看,不管是在训练过程还是前向推理过程,Stable Diffusion中的U-Net在每次循环迭代中Content Embedding部分始终保持不变,而Time Embedding每次都会发生变化。

和传统深度学习时代的U-Net一样,Stable Diffusion中的U-Net也是不限制输入图片的尺寸,因为这是个基于Transformer和卷积的模型结构

【3】Stable Diffusion中U-Net的训练过程与损失函数

在我们进行Stable Diffusion模型训练时,VAE部分和CLIP部分都是冻结的,所以说官方在训练SD系列模型的时候,训练过程一般主要训练U-Net部分。

我们之前我们已经讲过在Stable Diffusion中U-Net主要是进行噪声残差,在SD系列模型训练时和DDPM一样采用预测噪声残差的方法来训练U-Net,其损失函数如下所示:

到这里,Stable Diffusion U-Net的完整核心基础知识就介绍好了,欢迎大家在评论区发表自己的观点,也希望大家能多多点赞,Rocky会持续完善本文的全部内容,大家敬请期待!

【4】SD模型融合详解(Merge Block Weighted,MBW)

不管是传统深度学习时代,还是AIGC时代,模型融合永远都是学术界、工业界以及竞赛界的一个重要Trick。

在AI绘画领域,很多AI绘画开源社区里都有SD融合模型的身影,这些融合模型往往集成了多个SD模型的优点,同时规避了不足,让这些SD融合模型在开源社区中很受欢迎。

接下来Rocky将带着大家详细了解SD模型的模型融合过程与方法,大家可能会好奇为什么SD模型融合会在介绍SD U-Net的章节中讲到,原因是SD的模型融合方法主要作用于U-Net部分

首先,我们需要知道SD模型融合的形式,一共三种有如下所示:

  • SD模型 + SD模型 -> 新SD模型
  • SD模型 + LoRA模型 -> 新SD模型
  • LoRA模型 + LoRA模型 -> 新LoRA模型

参考:

1.深入浅出完整解析Stable Diffusion(SD)核心基础知识 - 知乎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/831834.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读笔记(AAAI 20)Order Matters

个人博客地址 注:部分内容参考自GPT生成的内容 论文笔记:Order Matters(AAAI 20) 用于二进制代码相似性检测的语义感知神经网络 论文:《Order Matters: Semantic-Aware Neural Networks for Binary Code Similarity Detection》…

MongoDB的分片集群

MongoDB分片技术 介绍 ​ 分片(sharding)是MongoDB用来将大型集合分割到不同服务器上采用的方法。分片这种说法起源于关系型数据库。但是实际上非关系型数据库在分片方面相比于传统的关系型数据库更有优势。 ​ 与MySQL分库方案对比,MongoDB…

Hibernate的QBC与HQL查询

目录 1、Hibernate的QBC查询 2、Hibernate的HQL查询 3、NatvieSQL原生查询 1、Hibernate的QBC查询 Hibernate具有一个直观的、可扩展的条件查询API public class Test { /** * param args */ public static void main(String[] args) { Session sessio…

kan 这是什么(想多了哈哈)

代码 import paddleclass Xus(paddle.nn.Layer):def __init__(self, head, head_dim):super().__init__()self.x_layer paddle.nn.Linear(head_dim, head * head_dim, bias_attrFalse)self.s_layer paddle.nn.Linear(head_dim, head * head_dim, bias_attrFalse)self.u_laye…

组合总和2(力扣40)

解题思路:因为这里不能有重复的组合,所以采取用下表used来判断其是否在前面出现过,如果出现过就直接跳过,同时判断是树层重复还是树枝重复,如果是树枝重复就不用跳过 具体代码如下: class Solution { pu…

Deep Learning Part Eight--Attention 24.5.4

01.在翻译、语音识别等将一个时序数据转换为另一个时序数据的任务中,时序数据之间常常存在对应关系 引入了Attention的概念,介绍了Attention的注意力机制: 困难出现,seq2seq的问题引入:固定化长度问题(过于…

【数学建模】矩阵微分方程

一、说明 我相信你们中的许多人都熟悉微分方程,或者至少知道它们。微分方程是数学中最重要的概念之一,也许最著名的微分方程是布莱克-斯科尔斯方程,它控制着任何股票价格。 ​​ 股票价格的布莱克-斯科尔斯模型 微分方程可以由数学中的许多…

java基于云计算的SaaS医院his信息系统源码 HIS云平台源码

目录 云HIS功能模块 1、预约挂号: 2、药库管理: 3、门诊医生站: 4、门诊费用: 5、药房管理: 6、治疗室(门诊护士工作站): 7、统计分析: 8、财务管理:…

香蕉新鲜度等级识别香蕉成熟度识别分类数据集13478张4类别

数据集类型:图像分类用,不可用于目标检测无标注文件 数据集格式:仅仅包含jpg图片,每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数):13478 分类类别数:4 类别名称:["overripe","rip…

STM32G474 CMAKE VSCODE FREERTOS 导入

一. 文件准备 1. 首先下载 freertos FreeRTOS - Free RTOS Source Code Downloads, the official FreeRTOS zip file release download 2. 移动 FreeRTOS-Kenel 到 moto_control 文件夹下。 3. 将 FreeRTOSConfig.h 放到 /Core/Inc 下面 4. 由于 FreeRTOSConfig.h 中使用了…

【数据结构】顺序表的基本操作实现

文章目录 前言一、顺序表的概念及结构二、顺序表的基本操作实现1.顺序表的创建2.顺序表初始化3.顺序表扩容4.头插和尾插5.头删和尾删6.查找7.任意位置插入8.任意位置删除9.顺序表的销毁 三、总结 前言 从本篇我们开始学习数据结构初阶的内容。 首先我们了解一下什么是线性表&…

【doghead】mac: clion2024.1启动崩溃

doghead 是在mac 下跑各种数据的因此,在配置了环境后, 进行mac 构建 【doghead】mac构建,首先对mac的clion进行安装 mac 下安装clion2024.1 之前可能装过crack的clion教育优惠的clion跟之前的应该不同clion2024.1 在mac的新系统下崩溃google下竟然没有…

腾讯云CentOS7使用Docker安装ElasticSearch与Kibana详细教程

文章目录 一、安装ElasticSearch二、安装Kibana 一、安装ElasticSearch 使用Docker拉取ElasticSearch镜像 这里版本选择的是7.15.2 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.22. 查看ElasticSearch的镜像id docker images3. 创建ElasticSearch容器 …

鸿蒙应用开发系列 篇一:鸿蒙系统概述

文章目录 系列文章鸿蒙系统的历史HarmonyOS 与 OpenHarmony鸿蒙系统的技术架构与核心特性内核层:安全与效率的双轮驱动系统服务层:分布式服务,重构连接的维度框架层:开发者的效率与创意舞台应用层:全场景应用生态的繁荣鸿蒙系统与其他操作系统与Android、iOS的比较:与AOS…

鸿蒙开发仿咸鱼TabBar

鸿蒙开发自定义TabBar,实现tabBar 上中间按钮凸起效果 第一步、定义数据模型 export default class TabItemData{defaultIcon: ResourceselectedIcon: Resourcetitle: stringisMiddle: booleanconstructor(defaultIcon:Resource, selectedIcon:Resource, title:st…

Java——数组的定义和使用

目录 1.什么是数组 2.创建数组 3.数组的使用 3.1获取数组长度 3.2遍历数组 3.3数组作为方法的参数 3.4数组作为参数的返回值 4.数组转字符串 5.数组拷贝 5.1Arrays.copyOf(arr,arr.length) 5.2Arrays.copyOfRange(arr,2,6) 1.什么是数组 数组就是具有相同属性的集合&am…

php中常见的运算符和使用方法

PHP中常见的运算符包括算术运算符、赋值运算符、比较运算符、逻辑运算符、位运算符、字符串运算符、三元条件运算符(也称为三目运算符)、递增/递减运算符等。以下是这些运算符的简要说明和使用方法: 算术运算符: :加法…

【设计模式】之装饰器模式

系列文章目录 【设计模式】之模板方法模式 【设计模式】之责任链模式 【设计模式】之策略模式 【设计模式】之工厂模式(三种) 前言 今天给大家介绍23种设计模式中的装饰器模式。🌈 一、什么是装饰器模式 装饰器模式(Decora…

【C++】文件

目录 文件文件分类文本文件的读写(ASCII文件)的读写打开文件打开文件的方式关闭文件将数据写入ASCII文件从ASCII文件读入数据 二进制存储对比ASCII和二进制存储用成员函数read和write读写二进制文件打开方式文件的读入与读出 文件 所谓文件,一般指存储在外部介质上…

c#学习基础1

一、复杂数据类型 1)概述 2)枚举 1.基本概念 枚举是一个比较特别的存在,它是一个被命名的整形常量的集合,一般用它来表示状态,类型等 1.1申明枚举和申明枚举变量 1.2申明枚举语法 2.在哪里申明枚举 3.枚举的使用 4…