深入浅出解析Stable Diffusion完整核心基础知识 | 【算法兵器谱】

news2024/11/22 1:03:57

Rocky Ding

公众号:WeThinkIn

写在前面

【算法兵器谱】栏目专注分享AI行业中的前沿/经典/必备的模型&论文,并对具备划时代意义的模型&论文进行全方位系统的解析,比如Rocky之前出品的爆款文章Make YOLO Great Again系列。也欢迎大家提出宝贵的优化建议,一起交流学习💪

大家好,我是Rocky。

2022年,Stable Diffusion横空出世,成为AI行业从传统深度学习时代过渡至AIGC时代的标志模型,并为工业界和投资界注入了新的活力,让AI再次性感

本文中,Rocky将深入浅出的讲解Stable Diffusion的核心知识,例举最有价值的应用场景,对Stable Diffusion的训练过程进行通俗易懂的分析,并尝试对其性能进行优化,Rocky希望我们能更好的入门Stable Diffusion及其背后的AIGC领域。

话不多说,在Rocky毫无保留的分享下,让我们开始学习吧!

So,enjoy:

正文开始

----【目录先行】----

Stable Diffusion核心基础内容

  1. Stable Diffusion模型原理

  2. Stable Diffusion模型的核心组件

  3. Stable Diffusion推理流程

Stable Diffusion经典应用场景

  1. 文本生成图片

  2. 图片生成图片

  3. 图片inpainting

  4. 使用controlnet辅助生成图片

  5. 超分辨率重建

Stable Diffusion训练过程

Stable Diffusion性能优化

----【Stable Diffusion核心基础内容】----

【一】Stable Diffusion模型原理

Stable Diffusion(SD)模型和GAN模型一样,是生成式模型,了解GAN模型的朋友都知道,生成式模型能够生成和训练集分布相似的输出结果(拟合数据分布),在计算机视觉领域是图片,在自然语言处理领域是文字。

下面是主流生成式模型各自的生成逻辑:

生成式模型的主流架构

Rocky在这里拿GAN详细展开讲讲,由于篇幅原因,VAE和Flow-based models这里就不过多介绍,感兴趣的朋友可以找Rocky私下交流。

GAN由生成器 G G G和判别器 D D D组成。其中,生成器主要负责生成相应的样本数据,输入一般是由高斯分布随机采样得到的噪声 Z Z Z。而判别器的主要职责是区分生成器生成的样本与 g t ( G r o u n d T r u t h ) gt(GroundTruth) gtGroundTruth样本,输入一般是 g t gt gt样本与相应的生成样本,我们想要的是对 g t gt gt样本输出的置信度越接近 1 1 1越好,而对生成样本输出的置信度越接近 0 0 0越好。与一般神经网络不同的是,GAN在训练时要同时训练生成器与判别器,所以其训练难度是比较大的

我们可以将GAN中的生成器比喻为印假钞票的犯罪分子,判别器则被当作警察。犯罪分子努力让印出的假钞看起来逼真,警察则不断提升对于假钞的辨识能力。二者互相博弈,随着时间的进行,都会越来越强。在图像生成任务中也是如此,生成器不断生成尽可能逼真的假图像。判别器则判断图像是 g t gt gt图像,还是生成的图像。二者不断博弈优化,最终生成器生成的图像使得判别器完全无法判别真假。

好的,讲完GAN,让我们回到SD模型。SD模型有两个最基本也是最经典的应用,分别是文生图(txt2pic)图生图(pic2pic)

SD文生图过程

文生图是指将一段文字输入到SD模型中,经过一定的迭代次数,SD模型输出一张符合输入文字描述的图片。比如上图中输入了“天堂,巨大的,海滩”,于是生成了一个美丽沙滩的图片。

SD图生图过程

而图生图在输入文字的基础上,再输入一张图片,SD模型将根据文字的提示,将图片进行丰富,比如上图中,SD模型将“海盗船”添加在之前那个美丽的沙滩上。

Rocky在这里也分享一些朋友生成的图片,整体上都非常逼真:

在这里插入图片描述

感受了SD模型强大的生成能力,大家可能会想到生成式领域上一个霸主模型GAN,与GAN模型不同的是,SD模型是属于扩散模型,并且是基于latent的扩散模型。

什么是扩散模型呢?用通俗的话来讲,就是将图像的生成过程分多步进行,逐步完善图像内容,经过20-50次的“扩散”循环,最终输出精致的图像。

下面是一个直观的例子,将随机高斯噪声矩阵通过SD模型的Inference过程,逐步去燥,最后生成一个小别墅的图片。

SD模型的Inference过程

那latent又是什么呢?基于latent的扩散模型可以在低维度的隐空间上进行“扩散”过程而不是在实际pixel空间,这样一来大大降低了内存占用和计算复杂性,这是常规扩散模型和latent扩散模型之间的主要区别。同样的,在训练中,latent扩散模型也将训练过程聚焦在latent空间中。

举个例子,如果SD模型中将数据矩阵缩小的倍数设为 8 8 8,那么原本尺寸为 [ 3 , 512 , 512 ] [3, 512, 512] [3,512,512]的数据矩阵就会进入 [ 3 , 64 , 64 ] [3, 64, 64] [3,64,64]的latent隐空间中,内存和计算量直接缩小 64 64 64倍,整体效率大大提升。

到这里,大家应该对SD模型的基本概念有一个清晰的认识了,Rocky这里再帮大家总结一下:

  1. SD模型是生成式模型,与GAN模型有很多相似的地方,输入可以是图片,也可以是文字,输出是图片。
  2. SD模型属于扩散模型,扩散模型的整理逻辑是生成过程分步化与迭代化,这给整个生成过程引入更多约束与优化提供了可能
  3. SD模型是基于latent的,将生成空间压缩到latent空间中,比起常规扩散模型,大大提高计算效率的同时,降低了内存占用,成为了SD模型爆发的关键一招
  4. 站在CTO视角,将维度拉到最高维,Rocky认为SD模型的整体流程是一个优化噪声的艺术

【二】Stable Diffusion模型的核心组件

SD模型主要由自动编码器(VAE),U-Net以及文本编码器三个核心组件构成。

SD模型文生图流程

  1. 自动编码器(VAE):VAE的编码器能够将输入图像转换为低维特征,作为U-Net的输入。VAE的解码器将隐特征升维解码成完整图像。不同的VAE结构能够为生成图片带来不同的细节与整体颜色。

VAE的主要工作

为什么VAE可以将图像压缩到一个非常小的潜空间后能再次对图像还原呢?虽然整个过程可以看作是一个有损压缩,但自然图像并不是随机的,它们具有很高的规律性:比如说一张脸上的眼睛、鼻子、脸颊和嘴巴之间遵循特定的空间关系,又比如说一只猫有四条腿,并且是一个特定的生物结构。所以如果我们生成的图像尺寸在 512 × 512 512 \times 512 512×512之上时,其实特征损失带来的影响非常小。

  1. U-Net:预测噪声残差,结合调度算法(PNDM,DDIM,K-LMS等)进行噪声重构,逐步将随机高斯噪声转化成图片的隐特征。U-Net整体结构一般由ResNet模块构成,并在ResNet模块之间添加CrossAttention模块用于接收文本信息。

常规U-Net结构

ResNet模块与CrossAttention模块的结合

  1. 文本编码器:将输入prompt进行编码,输出token embeddings向量(语意信息),通过CrossAttention方式送入扩散模型的U-Net中作为condition,对生成图像内容进行一定程度上的控制,目前SD默认的是CLIP text encoder。

【三】Stable Diffusion推理流程

想要运行Stable Diffusion(SD),我们可以直接使用diffusers的完整pipeline流程。

#首先,安装相关依赖
pip install diffusers transformers scipy ftfy accelerate

#读取diffuers库
from diffusers import StableDiffusionPipeline

#初始化SD模型,加载预训练权重
pipe = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")

#使用GPU加速
pipe.to("cuda")

#如GPU的内存少于10GB,可以加载float16精度的SD模型
pipe = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", revision="fp16", torch_dtype=torch.float16)

#接下来,我们就可以运行pipeline了
prompt = "a photograph of an astronaut riding a horse"

image = pipe(prompt).images[0]

# 由于没有固定seed,每次运行代码,我们都会得到一个不同的图片。

我们打开下载的预训练文件夹,可以看到预训练模型主要由以下几个部分组成:

text_encoder和tokenizer,scheduler,unet,vae。

其中text_encoder,scheduler,unet,vae分别代表了上面讲到过的SD模型的核心结构。

同时我们还可以看到Tokenizer文件夹,表示标记器。Tokenizer首先将Prompt中的每个词转换为一个称为标记(token)的数字,符号化(Tokenization)是计算机理解单词的方式。然后,通过text_encoder将每个标记都转换为一个768值的向量,称为嵌入(embedding),用于U-Net的condition。

Tokenizer的作用

有时候我们运行完pipeline之后,会出现纯黑色图片,这表示我们本次生成的图片触发了NSFW机制,出现了一些违规的图片,我们可以修改seed重新进行生成。

我们可以自己设置seed,来达到对图片生成的控制。

import torch

#manual_seed(1024):每次使用具有相同种子的生成器时,都会获得相同的图像输出。
generator = torch.Generator("cuda").manual_seed(1024)

image = pipe(prompt, guidance_scale=7.5, generator=generator).images[0]

将pipeline的完整结构梳理好之后,我们再对一些核心参数进行讲解:

  1. num_inference_steps。num_inference_steps表示我们对图片进行噪声优化的次数。一般来说,我们可以选择num_inference_steps = 20/25/50,数值越大,图片生成效果越好,但同时生成所需的时间就越长。

  2. guidance_scale,代表无分类指引(Classifier-free guidance,guidance_scale,CFG)是一个控制文本提示对扩散过程的影响程度的值。简单来说就是在加噪阶段将条件控制下预测的噪音和无条件下的预测噪音组合在一起来确定最终的噪声。通常guidance_scale可以选7-8.5之间,如果使用非常大的值,图像可能看起来不错,但多样性会降低。

其中 w w w代表CFG,当 w w w越大时,condition起的作用越大,即生成的图像更和输入文本一致,当 w w w被设置为 0 0 0时,图像生成是无条件的,文本提示会被忽略。

  1. 输出尺寸

SD在默认情况下会输出 512 × 512 512 \times 512 512×512尺寸的图片。我们也可以自定义设置图片尺寸,Rocky建议如下:

  1. 建议height和width都是8的倍数。
  2. 低于 512 512 512可能会导致图像质量较低。
  3. 创建非正方形图像的推荐方法是在一维中使用 512 512 512,另一个使用更大的值。
prompt = "a photograph of an astronaut riding a horse"

# Number of denoising steps
steps = 25         

# Scale for classifier-free guidance
CFG = 7.5

image = pipe(prompt, guidance_scale=CFG, height=512, width=768, num_inference_steps=steps).images[0]

除了将预训练模型整体加载,我们还可以将SD模型的不同组件单独加载:

from transformers import CLIPTextModel, CLIPTokenizer
from diffusers import AutoencoderKL, UNet2DConditionModel, PNDMScheduler
from diffusers import LMSDiscreteScheduler

# 单独加载VAE模型 
vae = AutoencoderKL.from_pretrained("runwayml/stable-diffusion-v1-5", subfolder="vae")

# 单独家在CLIP模型和tokenizer
tokenizer = CLIPTokenizer.from_pretrained("openai/clip-vit-large-patch14")
text_encoder = CLIPTextModel.from_pretrained("openai/clip-vit-large-patch14")

# 单独加载U-Net模型
unet = UNet2DConditionModel.from_pretrained("runwayml/stable-diffusion-v1-5", subfolder="unet")

# 单独加载调度算法
scheduler = LMSDiscreteScheduler(beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear", num_train_timesteps=1000)

----【Stable Diffusion经典应用场景】----

文本生成图像

输入:prompt

输入:图像

其中Load Checkpoint模块代表对SD模型的主要结构进行初始化(VAE,U-Net),CLIP Text Encode表示文本编码器,可以输入prompt和negative prompt,来控制图像的生成,Empty Latent Image表示初始化的高斯噪声,KSampler表示调度算法以及SD相关生成参数,VAE Decode表示使用VAE的解码器将低维度的隐空间特征转换成像素空间的生成图像。

图片生成图片

输入:图像 + prompt

输出:图像

其中Load Checkpoint模块代表对SD模型的主要结构进行初始化(VAE,U-Net),CLIP Text Encode表示文本编码器,可以输入prompt和negative prompt,来控制图像的生成,Load Image表示输入的图像,KSampler表示调度算法以及SD相关生成参数,VAE Encode表示使用VAE的编码器将输入图像转换成低维度的隐空间特征,VAE Decode表示使用VAE的解码器将低维度的隐空间特征转换成像素空间的生成图像。

与文字生成图片的过程相比,图片生成图片的预处理阶段,先把噪声添加到隐空间特征中。我们设置一个去噪强度(Denoising strength)控制加入多少噪音。如果它是0,就不添加噪音。如果它是1,则添加最大数量的噪声,使潜像成为一个完整的随机张量,如果将去噪强度设置为1,就完全相当于文本转图像,因为初始潜像完全是随机的噪声。

去噪强度(Denoising strength)控制噪音的加入量

图片inpainting

输入:图像 + mask + prompt

输出:图像

其中Load Checkpoint模块代表对SD模型的主要结构进行初始化(VAE,U-Net),CLIP Text Encode表示文本编码器,可以输入prompt和negative prompt,来控制图像的生成,Load Image表示输入的图像和mask,KSampler表示调度算法以及SD相关生成参数,VAE Encode表示使用VAE的编码器将输入图像和mask转换成低维度的隐空间特征,VAE Decode表示使用VAE的解码器将低维度的隐空间特征转换成像素空间的生成图像。

下面就是如何进行图像inpainting的直观过程:

在这里插入图片描述

使用controlnet辅助生成图片

输入:素描图 + prompt

输出:图像

其中Load Checkpoint模块代表对SD模型的主要结构进行初始化(VAE,U-Net),CLIP Text Encode表示文本编码器,可以输入prompt和negative prompt,来控制图像的生成,Load Image表示输入的ControlNet需要的预处理图,Empty Latent Image表示初始化的高斯噪声,Load ControlNet Model表示对ControlNet进行初始化,KSampler表示调度算法以及SD相关生成参数,VAE Decode表示使用VAE的解码器将低维度的隐空间特征转换成像素空间的生成图像。

使用ControlNet辅助生成图片

超分辨率重建

输入:prompt/(图像 + prompt)

输入:图像

其中Load Checkpoint模块代表对SD模型的主要结构进行初始化(VAE,U-Net),CLIP Text Encode表示文本编码器,可以输入prompt和negative prompt,来控制图像的生成,Empty Latent Image表示初始化的高斯噪声,Load Upscale Model表示对超分辨率重建模型进行初始化,KSampler表示调度算法以及SD相关生成参数,VAE Decode表示使用VAE的解码器将低维度的隐空间特征转换成像素空间的生成图像,Upscale Image表示将生成的图片进行超分。

----【Stable Diffusion训练过程】----

Stable Diffusion的整个训练过程在最高维度上可以看成是如何加噪声和如何去噪声的过程,并在针对噪声的“对抗与攻防”中学习到生成图片的能力

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

SD训练时的加噪过程

接着,让SD模型学习去噪过程,最后抽象出一个高维函数,这个函数能在纯噪声中“优化”噪声,得到一个干净样本。

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

SD训练时的去噪过程

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

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

多量级噪声

那么怎么让网络知道目前处于 K K K的哪一步呢?这时就需要Positional embeddings了,通过位置编码,将步数也传入网络中,从而让网络知道现在处于哪一步,和Transformer中的操作类似:

使用Positional embeddings对训练迭代的步数进行编码

----【Stable Diffusion性能优化】----

使用TF32精度

import torch

torch.backends.cuda.matmul.allow_tf32 = True

TF32在性能和精度上实现了平衡。下面是TF32精度的一些作用和优势:

  1. 加速训练速度:使用TF32精度可以在保持相对较高的模型精度的同时,加快模型训练的速度。
  2. 减少内存需求:TF32精度相对于传统的浮点数计算(如FP32)需要更少的内存存储。这对于训练大规模的深度学习模型尤为重要,可以减少内存的占用。
  3. 可接受的模型精度损失:使用TF32精度会导致一定程度的模型精度损失,因为低精度计算可能无法精确表示一些小的数值变化。然而,对于大多数深度学习应用,TF32精度仍然可以提供足够的模型精度。

使用FP16半精度

import torch
from diffusers import DiffusionPipeline

pipe = DiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16,
)

使用FP16半精度训练的优势:

减少了一半的内存占用,我们可以进一步将batch大小翻倍,并将训练时间减半。
一些GPU如V100, 2080Ti等针对16位计算进行了优化,能自动加速3-8倍。

对注意力模块进行切片

当模型中的注意力模块存在多个注意力头时,可以使用切片注意力操作,使得每个注意力头依次计算注意力矩阵,从而大幅减少内存占用,但随之而来的是推理时间增加约10%。

import torch
from diffusers import DiffusionPipeline

pipe = DiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    
    torch_dtype=torch.float16,
)
pipe = pipe.to("cuda")

# 切片注意力
pipe.enable_attention_slicing()

对VAE进行切片

和注意力模块切片一样,我们也可以对VAE进行切片,让VAE每次处理Batch(32)中的一张图片,从而大幅减少内存占用。

import torch
from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    
    torch_dtype=torch.float16,
)
pipe = pipe.to("cuda")

prompt = "a photo of an astronaut riding a horse on mars"
#切片VAE
pipe.enable_vae_slicing()
images = pipe([prompt] * 32).images

大图像切块

当想要生成4k或者更大的图像,并且内存不充裕时,可以使用图像切块的操作,让VAE的编码器与解码器对切块后的图像逐一处理,最后从容拼接生成大图。

import torch
from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16,
)
pipe = pipe.to("cuda")
prompt = "a beautiful landscape photograph"
# 大图像切块
pipe.enable_vae_tiling()

image = pipe([prompt], width=3840, height=2224, num_inference_steps=20).images[0]

CPU <-> GPU切换

可以将整个SD模型或者SD模型的部分模块权重加载到CPU中,只有等推理时再将需要的权重加载到GPU。

import torch
from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16,
)

#子模块CPU <-> GPU切换
pipe.enable_sequential_cpu_offload()

#整个SD模型CPU <-> GPU切换
pipe.enable_model_cpu_offload()

变换Memory Format

在CV领域,两种比较常见的memory format是channels first(NCHW)和channels last(NHWC)。将channels first转变成为channels last可能会提升推理速度,不过这也需要依AI框架和硬件而定。

在Channels Last内存格式中,张量的维度顺序为:(batch_size, height, width, channels)。其中,batch_size表示批处理大小,height和width表示图像或特征图的高度和宽度,channels表示通道数。

相比而言,Channels First是另一种内存布局,其中通道维度被放置在张量的第二个维度上。在Channels First内存格式中,张量的维度顺序为:(batch_size, channels, height, width)。

选择Channels Last或Channels First内存格式通常取决于硬件和软件平台以及所使用的深度学习框架。不同的平台和框架可能对内存格式有不同的偏好和支持程度。

在一些情况下,Channels Last内存格式可能具有以下优势:

  1. 内存访问效率:在一些硬件架构中,如CPU和GPU,Channels Last内存格式能够更好地利用内存的连续性,从而提高数据访问的效率。
  2. 硬件加速器支持:一些硬件加速器(如NVIDIA的Tensor Cores)对于Channels Last内存格式具有特定的优化支持,可以提高计算性能。
  3. 跨平台兼容性:某些深度学习框架和工具更倾向于支持Channels Last内存格式,使得在不同的平台和框架之间迁移模型更加容易。

需要注意的是,选择内存格式需要根据具体的硬件、软件和深度学习框架来进行评估。某些特定的操作、模型结构或框架要求可能会对内存格式有特定的要求或限制。因此,建议在特定环境和需求下进行测试和选择,以获得最佳的性能和兼容性。

print(pipe.unet.conv_out.state_dict()["weight"].stride())  
# 变换Memory Format
pipe.unet.to(memory_format=torch.channels_last)  
print(pipe.unet.conv_out.state_dict()["weight"].stride()) 

使用xFormers

使用xFormers插件能够让注意力模块优化运算,提升20%左右的运算速度。

from diffusers import DiffusionPipeline
import torch

pipe = DiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16,
).to("cuda")

# 使用xFormers
pipe.enable_xformers_memory_efficient_attention()

精致的结尾

到这里,Stable Diffusion的核心知识就完整展现在我们的面前了,希望在AIGC时代中,大家能和Rocky一起,飞速成长!

Rocky将算法高价值面试知识点即“三年面试五年模拟”之独孤九剑秘籍前十二式进行汇总梳理成汇总篇,并制作成pdf版本,大家可在公众号后台 【精华干货】菜单或者回复关键词“三年面试五年模拟” 进行取用。

除此之外Rocky还将YOLOv1-v7全系列大解析也制作成相应的pdf版本,大家可在公众号后台 【精华干货】菜单或者回复关键词“YOLO” 进行取用。

Rocky一直在运营技术交流群(WeThinkIn-技术交流群),这个群的初心主要聚焦于技术话题的讨论与学习,包括但不限于算法,开发,竞赛,科研以及工作求职等。群里有很多人工智能行业的大牛,欢迎大家入群一起学习交流~(请添加小助手微信Jarvis8866,拉你进群~)

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

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

相关文章

笔试强训错题总结(一)

笔试强训错题总结 文章目录 笔试强训错题总结选择题编程题连续最大和不要二最近公共祖先最大连续的bit数幸运的袋子手套 选择题 以下程序的运行结果是&#xff08;&#xff09; #include <stdio.h> int main(void) {printf("%s , %5.3s\n", "computer&q…

<Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的beep驱动

&#xff1c;Linux开发&#xff1e;驱动开发 -之-基于pinctrl/gpio子系统的beep驱动 交叉编译环境搭建&#xff1a; &#xff1c;Linux开发&#xff1e; linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下&#xff1a; &#xff1c;Linux开发&#xff1e; -之-系统移植…

如何在华为OD机试中获得满分?Java实现【人民币转换】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

认识Servlet---1

hi ,大家好,今天为大家带来Servlet相关的知识,并且实现第一个程序 &#x1f389;1.什么是Servlet &#x1f389;2.使用Servlet写一个hello程序 &#x1f33b;&#x1f33b;&#x1f33b;1.创建项目 &#x1f33b;&#x1f33b;&#x1f33b;2.引入依赖 &#x1f33b;&…

GitHub基本概念

创建日期: 2018-09-22 09:50:06 Git & GitHub Git是一个版本控制软件&#xff1a; 读作[gɪt] ,拼音读作gē y te。 Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed an…

STM32之温湿度LCD显示并上传服务器

目录 项目需求 项目框图 硬件清单 LCD1602介绍及实战 硬件接线 引脚封装 代码实现 DHT11介绍及实战 硬件接线 引脚封装 代码实现 项目设计及实现 项目设计 项目实现 项目需求 使用温湿度传感器模块&#xff08; DHT11 &#xff09;获取温度及湿度&#xff0c…

推荐计算机领域的几本入门书籍

人工智能入门&#xff1a; 人工智能&#xff1a;现代方法&#xff08;第4版&#xff09;揭示AI与chatgpt的奥秘&#xff0c;详解人工智能的发展与未来&#xff01; 推荐理由&#xff1a;系统性总结人工智能的方方面面&#xff0c;国际人工智能领域专家斯图尔特罗素撰写人工智能…

YOLO-NAS对象检测算法再一次颠覆YOLO系列算法——已超越YOLOv8

对象检测彻底改变了机器感知和解释人类世界的方式。这是计算机视觉中一项特别关键的任务,使机器能够识别和定位图像或视频中的物体。如自动驾驶汽车、面部识别系统等。推动对象检测进步的一个关键因素是发明了神经网络架构。强大的神经网络推动了对象检测的进步,增强了计算机…

Meta Learning

Meta Learning&#xff08;元学习&#xff09;是一种机器学习技术&#xff0c;它的核心思想是学习如何学习。 Meta Learning的目标是从以前的学习经验中学习到通用的学习策略和模式&#xff0c;以便在新的任务上快速适应和学习。 Meta Learning的核心思想是将学习任务视为元任…

Vivado下阻塞赋值和非阻塞赋值的对比

Verilog 基础知识 中已经介绍过了阻塞赋值和非阻塞赋值的区别&#xff0c;下面通过一个在Vivado中的简单例子来直观的反映两者的不同。 首先给出设计源代码如下。 module block(a,b,c,clk,x);input x;input clk;output reg a,b,c;always(posedge clk) begina x; //阻塞赋值…

零钱兑换,凑零钱问题,从暴力递归到动态规划(java)

凑零钱问题&#xff0c;从暴力递归到动态规划 leetcode 322 题 零钱兑换暴力递归&#xff08;这个会超时&#xff0c;leetcode 跑不过去&#xff09;递归缓存 leetcode 322 题 零钱兑换 322 零钱兑换 - 可以打开链接测试 给你一个整数数组 coins &#xff0c;表示不同面额的硬…

[MAUI]模仿Chrome下拉标签页的交互实现

文章目录 创建粘滞效果的圆控件贝塞尔曲线绘制圆创建控件创建形变可控形变形变边界形变动画 创建手势控件创建页面布局更新拖拽物位置其它细节 项目地址 今天来说说怎样在 .NET MAUI 中制作一个灵动的类标签页控件&#xff0c;这类控件常用于页面中多个子页面的导航功能。 比如…

《数据库应用系统实践》------ 公园游客日流量管理系统

系列文章 《数据库应用系统实践》------ 公园游客日流量管理系统 文章目录 系列文章一、需求分析1、系统背景2、 系统功能结构&#xff08;需包含功能结构框图和模块说明&#xff09;3&#xff0e;系统功能简介 二、概念模型设计1&#xff0e;基本要素&#xff08;符号介绍说明…

【阅读笔记】概率预测之MQ-RNN(含Pytorch代码实现)

本文作为自己阅读论文后的总结和思考&#xff0c;不涉及论文翻译和模型解读&#xff0c;适合大家阅读完论文后交流想法&#xff0c;关于论文翻译可以查看参考文献。论文地址&#xff1a;https://arxiv.org/abs/1711.11053 MQ-RNN 一. 全文总结二. 研究方法三. 结论四. 创新点五…

谷歌推出免费AI编程神器Colab,欲将Copilot拉下神坛

在如今的AI编码工具领域&#xff0c;微软旗下的Github Copilot可以算得上是一家独大&#xff0c;而作为老对手的谷歌显然并不愿屈服于此。 近日&#xff0c;谷歌通过其官网高调发文宣布&#xff0c;将为研发工具Google Colaboratory&#xff08;Colab&#xff09;加入全新的AI…

DAY 68 redis高可用的主从复制、哨兵、cluster集群

Redis 高可用 什么是高可用 在web服务器中&#xff0c;高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 但是在Redis语境中&#xff0c;高可用的含义似乎要宽泛一些&#xff0c;除了保证提供正常服…

RT-Thread memheap 开启多块 SRAM的方法

验证环境 NUCLEO-L476RG 开发板&#xff0c;板载 STM32L476RGT6&#xff08;96K SARM1 32K SRAM2&#xff09; Win10 64 位 Keil MDK 5.36 RT-Thread 5.0.1 版本&#xff08;2023-05-28 master 主线&#xff09; 功能描述 最近在研究 RT-Thread 内存的管理&#xff0c;熟…

Linux内核源码分析 2:Linux内核版本号和源码目录结构

一、Linux的版本 1. 稳定版和开发版 Linux内核主要分为两种版本&#xff1a; 稳定版&#xff08;长期支持版&#xff09;&#xff1a;稳定版的内核具有工业级的强度&#xff0c;可以广泛地应用和部署。而每一代新推出的稳定版内核大部分都只是修正了一些Bug或是加入了一些新的…

【网络协议详解】——FTP系统协议(学习笔记)

目录 &#x1f552; 1. 概述&#x1f552; 2. 工作原理&#x1f558; 2.1 两个连接 &#x1f552; 3. 相关命令与处理&#x1f558; 3.1 接入命令&#x1f558; 3.2 文件管理命令&#x1f558; 3.3 数据格式化命令&#x1f558; 3.4 端口定义命令&#x1f558; 3.5 文件传输命令…

计算机组成原理 期末复习笔记

&#x1f331;博客主页&#xff1a;大寄一场. &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 目录 前言 第一章 计算机系统概论计算机软件的发展 计算机硬件的基本组成 计算机系统的层次结构 计算机的性能指标 第二章 数据表示 与 第三章 数据运算与运…