Stable Diffusion XL(SDXL)原理详解

news2024/12/23 16:33:52

在这里插入图片描述

技术报告:SDXL: Improving Latent Diffusion Models for High-Resolution Image Synthesis
官方代码:Stability-AI-generative-models
模型权重:HuggingFace-Stability AI
非官方代码:Linaqruf/kohya-trainer
diffuser库:diffusers/pipelines/stable_diffusion_xl

通过各种实验验证,SDXL已经超越了先前发布的各种版本的Stable Diffusion,并且与当前未开源的文生图SOTA模型(如midjorney)具有不相上下的效果。本文将介绍SDXL相比于之前的SD(SD1.5, SD2.0等)改进之处。相比之前各个版本的SD,SDXL 的主要改进之处在于:

  • 使用了更大的Unet backbone,大约是之前版本SD的3倍
  • 使用了几个简单但是非常有效的训练技巧,包括图像尺寸条件化策略,图像裁剪参数条件化以及多尺度训练等
  • 增加了一个refinement 模块来改善生成图片的质量

本文主要根据技术报告SDXL: Improving Latent Diffusion Models for High-Resolution Image Synthesis来讲解SDXL的原理,在下一篇文章中我们会通过源码解读来进一步理解SDXL的改进点。

1. SDXL原理

1.1 整体架构

SDXL和之前的版本一样也是基于latent diffusion架构,对于latent diffusion,首先会采用一个autoencoder模型来图像压缩为latent,然后扩散模型用来生成latent,生成的latent可以通过autoencoder的decoder来重建出图像。SDXL整体模型结构如下图所示:
在这里插入图片描述
相比之前SD版本,Stable Diffusion XL是一个二阶段的级联扩散模型,包括Base模型和Refiner模型。其中Base模型的主要工作和Stable Diffusion一致,具备文生图,图生图,图像inpainting等能力。在Base模型之后,级联了Refiner模型,对Base模型生成的图像Latent特征进行精细化,其本质上是在做图生图的工作。

相比SD1.x和SD2.x,SDXL使用了更大的backbone,下图展示了三者结构和参数量上的对比,SDXL的参数量大约为之前版本的SD的3倍
在这里插入图片描述

1.2 VEA

SDXL的autoencoder依然采用KL-f8,但是并没有采用之前的autoencoder,而是基于同样的架构采用了更大的batch size(256 vs 9)重新训练,同时对模型的参数采用了EMA(指数移动平均),从而改善生成图片的局部和高频细节。重新训练的VAE模型相比之前的模型,其重建性能有一定的提升,下图展示了在COCO2017验证集上的测试结果。PNSR和SSIM指标越大越好,LPIPS和FID指标越小越好,具体可参考文章[1][2]。
在这里插入图片描述
上表中的三个VAE模型其实模型结构是完全一样,其中SD-VAE 2.x只是在SD-VAE 1.x的基础上重新微调了decoder部分,但是encoder权重是相同的,所以两者的latent分布是一样的,两个VAE模型是都可以用在SD 1.x和SD 2.x上的。但是SDXL-VAE是完全重新训练的,它的latent分布发生了改变,不可以将SDXL-VAE应用在SD 1.x和SD 2.x上。在将latent送入扩散模型之前,我们要对latent进行缩放来使得latent的标准差尽量为1,由于权重发生了改变,所以SDXL-VAE的缩放系数也和之前不同,之前的版本采用的缩放系数为0.18215,而SDXL-VAE的缩放系数为0.13025。

1.3 Unet

SDXL相比之前的版本,Unet的变化主要有如下两点:

  • 采用了更大的UNet,如1.1章节中的表可以看到,之前版本的SD Unet 参数量为860M,而SDXL参数量达到了2.6B,大约是其的3倍。
  • Unet 结构发生了改变,从之前的4stage变成了3stage

图1.3.1和图1.3.2分别展示了SDXL和SD1.x的Unet结构图
在这里插入图片描述

图1.3.1 SDXL Unet结构

请添加图片描述

图1.3.2 SD1.x Unet结构

如上图所示,相比之前的SD,SDXL的第一个stage采用的是普通的DownBlock2D,而不是采用基于attention的CrossAttnDownBlock2D;此外,SDXL只用了3个stage,只进行了两次2x下采样,而之前的SD使用4个stage,包含3个2x下采样。SDXL的网络宽度(channels)相比之前的版本并没有改变,3个stage的特征channels分别是320、640和1280。

SDXL参数量的增加主要是使用了更多的transformer blocks,在之前的版本,每个包含attention的block只使用一个transformer block(self-attention -> cross-attention -> ffn),但是SDXL中stage2和stage3的两个CrossAttnDownBlock2D模块中的transformer block数量分别设置为2和10,并且中间的MidBlock2DCrossAttn的transformer blocks数量也设置为10。

1.4 text encoder

SD 1.x采用的text encoder是123M的OpenAI CLIP ViT-L/14,SD 2.x将text encoder升级为354M的OpenCLIP ViT-H/14,SDXL不仅采用了更大的OpenCLIP ViT-bigG(参数量为694M),而且同时也用了OpenAI CLIP ViT-L/14,分别提取两个text encoder的倒数第二层特征,其中OpenCLIP ViT-bigG的特征维度为1280,而CLIP ViT-L/14的特征维度是768,两个特征concat在一起总的特征维度大小是2048,这也就是SDXL的context dim。

如下图所示,OpenCLIP ViT-bigG相比OpenCLIP ViT-H/14,在性能上有一定的提升,其中在ImageNet上zero-shot性能为80.1%
在这里插入图片描述
此外,SDXL还提取了OpenCLIP ViT-bigG的 pooled text embedding(用于CLIP对比学习所使用的特征),将其映射到time embedding的维度并与之相加

1.5 训练技巧

SDXL在训练上也使用了很多技巧,主要有如下几点

  • 图像尺寸条件化
  • 图像裁剪参数条件
  • 多尺度(宽高比)图片训练

1.5.1 图像尺寸参数条件

Stable Diffusion 1.x/2.x 的训练过程中,主要分成两个阶段,先在256x256的图像尺寸上进行预训练,然后在512x512的图像尺寸上继续训练。这两个阶段的训练过程都要对图像最小尺寸进行约束。第一阶段中,会将尺寸小于256x256的图像舍弃;在第二阶段,会将尺寸小于512x512的图像舍弃。这样会导致训练数据中的大量数据被丢弃,数据利用率不高,而且很可能导致模型性能和泛化性的降低。

上述问题,一般思路是借助超分模型将尺寸过小的图像放大。但是超分模型可能会在对图像超分的同时会引入一些噪声伪影,影响模型的训练,导致生成一些模糊的图像。

Stable Diffusion XL为了在解决数据集利用率问题的同时不引入噪声伪影,将U-Net(Base)模型与原始图像分辨率相关联,核心思想是将输入图像的原始高度和宽度 c s i z e = ( w origin , h origin ) c_{\text size}=(w_\text {origin}, h_\text {origin}) csize=(worigin,horigin) 作为额外的条件嵌入U-Net模型中,height和width分别都用傅里叶特征编码,然后将特征concat后加在Time Embedding上,将图像尺寸引入训练过程,这样模型在训练过程中能够学习到图像的原始分辨率信息。在推理阶段,用户可以通过 c size c_\text {size} csize 参数设置期望的分辨率,从而更好地适应不同尺寸的图像生成。

在这里插入图片描述
上图展示了采用这种方案得到的512x512模型,送入不同的size时的生成图像对比,可以看到模型已经学到了识别图像分辨率,当输入低分辨率时,生成的图像比较模糊,但是当提升size时,图像质量逐渐提升

为了定量分析图像尺寸条件化的效果,作者在ImageNet上基于类别条件训练和验证LDM。作者分别训练了三个模型,其效果如下图所示:

  • CIN-512 only:丢弃最小边小于512的所有图片,这导致最终训练集只有70K
  • CIN-nocond:使用了所有的训练样本,但是训练时没有加图像尺寸条件
  • CIN-size-cond:使用所有图片,并在训练时使用了图像尺寸条件

请添加图片描述
作者认为CIN-512-only 的差表现主要是因为模型在小数据集上过拟合了,而CIN-nocond效果没有CIN-size-cond的好是因为其生成的模糊图片造成了相似度更低。

1.5.2 图像裁剪参数条件

生成式模型中典型的预处理方式是先调整图像尺寸,使得最短边与目标尺寸匹配,然后再沿较长边对图像进行随机裁剪或者中心裁剪。虽然裁剪是一种数据增强方法,但是训练中对图像裁剪导致的图像特征丢失,可能会导致模型在图像生成阶段出现不符合训练数据分布的特征.

如下图所示,在SD1.x/2.x中会存在生成图像不完整的情况,比如生成的猫的头被裁剪了,并没有生成一个完整的猫。这很大可能就是在训练过程中数据预处理阶段的随机裁剪造成的。
在这里插入图片描述
NovelAI在之前就发现了这个问题(NovelAI Aspect Ratio Bucketing Source Code Release),并提出了基于分桶(Ratio Bucketing)的多尺度训练策略,其主要思想是先将训练数据集按照不同的长宽比(aspect ratio)进行分桶(buckets)。在训练过程中,每次在buckets中随机选择一个bucket并从中采样Batch个数据进行训练。将数据集进行分桶可以大量减少裁剪图像的操作,并且能让模型学习多尺度的生成能力;但相对应的,预处理成本大大增加。

Stable Diffusion XL使用了一种简单而有效的条件化方法,即图像裁剪参数条件化策略。其主要思想是在加载数据时,将左上角的裁剪坐标 ( c t o p , c left ) (c_{\text top}, c_\text {left}) (ctop,cleft) 通过傅里叶编码,并与原始图像尺寸一起作为额外的条件嵌入U-Net模型,从而在训练过程中让模型学习到对图像裁剪的认识。在推理时,我们只需要将这个坐标 ( c t o p , c left ) (c_{\text top}, c_\text {left}) (ctop,cleft) 设置为(0, 0)就可以得到物体居中的图像。

下图展示了采用不同的crop坐标的生成图像对比,可以看到(0, 0)坐标可以生成物体居中而无缺失的图像,通过调整坐标 ( c t o p , c left ) (c_{\text top}, c_\text {left}) (ctop,cleft) 可以让模型生成对应裁剪的图像

在这里插入图片描述
SDXL在训练过程中,可以将两种条件注入(size and crop conditioning)结合在一起使用。在结合一起使用时,首先在通道维度将两者特征向量连接,然后加到Time Embedding上。两个条件结合使用的伪代码如下图所示。
在这里插入图片描述

1.5.3 多尺度训练

现实数据集中包含不同宽高比的图像,然而文生图模型输出一般都是512x512或者1024x1024,作者认为这并不是一个好的结果,因为不同宽高比的图像有广泛的应用场景,比如(16:9)。基于以上原因,作为对模型进行了多尺度图像微调。

经过预训练之后,作者借鉴NovelAI所提出的方案 NovelAI Aspect Ratio Bucketing,将数据集中图像按照不同的长宽比划分到不同的buckets上(按照最近邻原则),SDXL所设置的buckets如下表所示,虽然不同的bucket的aspect ratio不同,但是像素总数(宽x高)都接近1024x1024,相邻的bucket其height或者width相差64个pixels。
请添加图片描述
在训练过程中,每个step可以在不同的buckets之间切换,每个batch的数据都是从相同的bucket中采样得到。在多尺度训练中,SDXL也将bucket size c a r = ( h tgt , w tgt ) c_{ar}=(h_\text{tgt}, w_ \text{tgt}) car=(htgt,wtgt)(即target size)作为条件加入UNet中,这个条件注入方式和之前图像原始尺寸条件注入一样。将target size作为条件,其实是让模型能够显示地学习到多尺度(或aspect ratio)。 在多尺度微调阶段,SDXL依然采用前面所说的size and crop conditioning,虽然crop conditioning和多尺度微调是互补方案,但是这里也依然保持这个条件注入。经过多尺度微调后,SDXL就可以生成不同aspect ratio的图像,SDXL默认生成1024x1024的图像。

1.5.4 小结

SDXL总共增加了4个额外的条件注入到UNet,它们分别是pooled text embedding,original size,crop top-left coord和target size(bucket size)。对于后面三个条件,它们可以像timestep一样采用傅立叶编码得到特征,然后我们这些特征和pooled text embedding拼接在一起,最终得到维度为2816(1280+25623)的特征。我们将这个特征采用两个线性层映射到和time embedding一样的维度,然后加在time embedding上即可,具体的实现代码如下所示

import math
from einops import rearrange
import torch

batch_size =16
# channel dimension of pooled output of text encoder (s)
pooled_dim = 1280
adm_in_channels = 2816
time_embed_dim = 1280

def fourier_embedding(inputs, outdim=256, max_period=10000):
    """
    Classical sinusoidal timestep embedding
    as commonly used in diffusion models
    : param inputs : batch of integer scalars shape [b ,]
    : param outdim : embedding dimension
    : param max_period : max freq added
    : return : batch of embeddings of shape [b, outdim ]
    """
    half = outdim // 2
    freqs = torch.exp(
        -math.log(max_period)
            * torch.arange(start=0, end=half, dtype=torch.float32)
            / half
    ).to(device=inputs.device)
    args = timesteps[:, None].float() * freqs[None]
    embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
    if dim % 2:
        embedding = torch.cat(
            [embedding, torch.zeros_like(embedding[:, :1])], dim=-1
        )
    return embedding


def cat_along_channel_dim(x: torch.Tensor,) -> torch.Tensor:
    if x.ndim == 1:
        x = x[... , None]
 assert x . ndim == 2
 b, d_in = x.shape
    x = rearrange(x, "b din -> (b din)")
    # fourier fn adds additional dimension
    emb = fourier_embedding(x)
    d_f = emb.shape[-1]
    emb = rearrange(emb, "(b din) df -> b (din df)",
                     b=b, din=d_in, df=d_f)
 return emb


def concat_embeddings(
    # batch of size and crop conditioning cf. Sec. 3.2
    c_size: torch.Tensor,
    c_crop: torch.Tensor,
    # batch of target size conditioning cf. Sec. 3.3
    c_tgt_size: torch.Tensor ,
    # final output of text encoders after pooling cf. Sec . 3.1
    c_pooled_txt: torch.Tensor,
) -> torch.Tensor:
    # fourier feature for size conditioning
    c_size_emb = cat_along_channel_dim(c_size)
 # fourier feature for size conditioning
 c_crop_emb = cat_along_channel_dim(c_crop)
 # fourier feature for size conditioning
 c_tgt_size_emb = cat_along_channel_dim(c_tgt_size)
 return torch.cat([c_pooled_txt, c_size_emb, c_crop_emb, c_tgt_size_emd], dim=1)

# the concatenated output is mapped to the same
# channel dimension than the noise level conditioning
# and added to that conditioning before being fed to the unet
adm_proj = torch.nn.Sequential(
    torch.nn.Linear(adm_in_channels, time_embed_dim),
    torch.nn.SiLU(),
    torch.nn.Linear(time_embed_dim, time_embed_dim)
)

# simulating c_size and c_crop as in Sec. 3.2
c_size = torch.zeros((batch_size, 2)).long()
c_crop = torch.zeros((batch_size, 2)).long ()
# simulating c_tgt_size and pooled text encoder output as in Sec. 3.3
c_tgt_size = torch.zeros((batch_size, 2)).long()
c_pooled = torch.zeros((batch_size, pooled_dim)).long()
 
# get concatenated embedding
c_concat = concat_embeddings(c_size, c_crop, c_tgt_size, c_pooled)
# mapped to the same channel dimension with time_emb
adm_emb = adm_proj(c_concat)

1.6 refiner

作者发现通过上述方式训练得到的LDM有时候生成的图片局部细节较差,如下图所示,左边是未使用refiner模型产出结果,右边是级联了refiner模型产出结果。
在这里插入图片描述为了提高生成质量,使用高质量和高分辨率的图像在相同的隐空间(latent space)中又训练了一个单独的LDM(通常称之前训练的LDM是base模型,后面训练的LDM是refiner模型)。refiner model是和base model采用同样VAE的一个latent diffusion model,但是它只在使用较低的noise level进行训练(即只在前200 timesteps上)。在推理阶段,首先用base model生成latent,然后我们给这个latent加一定的噪音(采用扩散过程),并使用refiner model进行去噪,并且输入和base model相同的prompt。增加级联后的模型结构如下图所示。
在这里插入图片描述
refiner model和base model在结构上有一定的不同,其UNet的结构如下图所示,refiner model采用4个stage,第一个stage采用没有attention的DownBlock2D,网络的特征维度采用384,而base model是320。另外,refiner model的attention模块中transformer block数量均设置为4。refiner model的参数量为2.3B,略小于base model。refiner model的text encoder只使用了OpenCLIP ViT-bigG,也是提取倒数第二层特征以及pooled text embed。
在这里插入图片描述
下图展示了增加refiner model和没有增加refiner model生成图片的对比,可见增加refiner model后确实能够改善人物脸部和背景的细节。
在这里插入图片描述
在这里插入图片描述

1.7 Put All Together

上文我们介绍了SDXL的各个模块,较为分散。现在我们将所有模块合并,来了解SDXL的总体训练过程。

总的来说训练SDXL是一个多阶段过程。

  • 首先在内部数据集上对base模型进行预训练:使用255x256分辨率的图像,batch size设置成2048,训练60万个step,这里同时使用了上文所述的size和crop conditioning。
  • 在512 x 512 分辨率的图像上继续训练20万step
  • 最后在图像总分辨率约为1024x1024的图片上进行多尺度训练,这里训练同时使用了noise-offset技巧

注意以过程是SDXL训练base model的过程,技术报告中并未提及refiner模型训练的具体流程,但猜测与base model可能不太相同,作者强调了refiner model关注于高质量、高分辨率的图片。

1.8 noise-offset

章节1.7中的第三点中提到使用了noise-offset技巧,这里简单介绍介绍下整个技巧:
如果试图让 Stable Diffusion 生成\特别暗或特别亮的图像,它几乎总是生成平均亮度值相对接近0.5的图像(全黑图像为0,全白图像为1),如下图所示,四个prompt 分别为:Top left: A dark alleyway in a rainstorm (0.301); Top right: Monochrome line-art logo on a white background (0.709); Bottom left: A snow-covered ski slope on a sunny day (0.641); Bottom right: A town square lit only by torchlight (0.452)
在这里插入图片描述
之所以会出现这个问题,是因为训练和测试过程的不一样,SD所使用的 noise scheduler其实在最后一步并没有将图像完全变成随机噪音,这使得训练过程中学习是有偏的,但是测试过程中,我们是从一个随机噪音开始生成的,这种不一致就会出现一定的问题。offset-noise方法就是在训练过程中给采用的噪音加上一定的offset即可,具体的实现代码如下所示:

# Sample noise that we'll add to the latents
noise = torch.randn_like(latents)
if args.noise_offset:
    # https://www.crosslabs.org//blog/diffusion-with-offset-noise
    noise += args.noise_offset * torch.randn((latents.shape[0], latents.shape[1], 1, 1), device=latents.device
)

加上noise-offset后,同样是上面的promt,生成结果如下所示
在这里插入图片描述

2. SDXL效果

2.1 与SOTA模型对比

在这里插入图片描述

2.2 与Midjourney5.1比较

这里是基于PartiPrompts来进行对比的,PartiPrompts是谷歌在Parti这个工作中所提出的文生图测试prompts,它包含不同的类别比如动物和人等。

首先作者做了一个整体的测试,每个类别随机选择5个prompts分别使用SDXL和Midjourney v5.1生成4个1024x1024的图像,然后人工来投票,最终的对比结果如下所示,SDXL以微弱的优势战胜Midjourney v5.1(54.9% vs 44.1%)。
在这里插入图片描述
然后作者又在不同类目上进行了对比
在这里插入图片描述

2.3 与SD1.x相比

下图展示了用户在SD1.x和SDXL模型结果的偏好程度
在这里插入图片描述
下图比较了SD1.x和SDXL在CLIP score和FID score两个指标上的对比。从CLIP score来看,SDXL采用了更强的text encoder,其CLIP score是最高的,但是从FID来看,SD 1.5是最低的(最好),而SDXL反而是最高(最差)的,直接用FID往往并不能很好地衡量图像的生成质量,因此和上图中人工测评相结合更能展示SDXL的真实表现
在这里插入图片描述
下面还展示了一些定性分析结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. SDXL局限性

尽管SDXL在生成真实、复杂图像方面相比上一代SD有了非常大的进步,最终效果也是让人足够惊艳,但是仍然存在一些问题,下图展示了SDXL的一些失败case
在这里插入图片描述

  • 生成复杂结构的物体(如人手)仍然不够好。作者认为出现这样的原因可能是手在每个图片中的(姿势等)差异都比较大,这很难让模型学习到真实3D知识
  • 模型生成的图像还是无法达到完美的逼真度,如微妙的灯光效果或微小的纹理变化等
  • 该模型的训练过程严重依赖于大规模数据集,这可能会无意中引入社会和种族偏见
  • 在样本包含多个对象或主题的情况下,模型可能会出现一种称为“概念混淆(concept bleeding)”的现象(即不同视觉元素的合并或重叠)。如下图,输入prompt为A portrait photo of a kangaroo wearing an orange hoodie and blue sunglasses standing on the grass in front of the Sydney Opera House holding a sign on the chest that says "SDXL"!,可见第三幅图出现了橙色的眼镜,这里是和橙色的外套弄混淆了
    在这里插入图片描述
    另外的一个case如下,输入prompt为:a baby penguin wearing a blue hat, red gloves, green shirt, and yellow pants,可见其将蓝色帽子和红色手套弄混淆了
    在这里插入图片描述
    作者认为这个问题主要原因在于预训练的文本编码器:首先text-encoder训练时将所有信息压缩到一个token里,导致属性和物品无法正确对应,其次训练时用的对比损失也会导致整个问题的发生,因为要模型正确区分这种对应关系需要不同的属性、物品对应关系的负样本出现在一个batch里,这显然很难。
  • 生成清晰且比较长的文字仍然比较困难,生成的文本可能包含随机字符,如下图所示,输入prompt为:a green sign that says "very deep learning" and is at the edge of the Grand Canyon
    在这里插入图片描述

综上所述,尽管SDXL模型在图像生成方面具有显著的优势,但也存在一定的局限性。与合成复杂的结构、实现完美的真实感、进一步解决偏见、减轻概念混淆和改进文本渲染相关的挑战突出了未来研究和优化的途径。作者也提出了未来需要进一步改进的工作:

  • 简化两阶段为单阶段模型:当前模型是base model + refiner mode 的两阶段模型,这造成需要更大内存来加载两个大模型,且对生成速度造成了很大影响
  • 提高文本生成能力:与之前的SD相比,使用更大的text encoder提高了文本渲染能力,但是与byte-level的tokenizer相结合或简单的将模型进一步增大也许会进一步提升文本生成能力
  • 模型结构可继续改进:可以尝试基于transformer的结构
  • 知识蒸馏:通过知识蒸馏来减小模型规模,从而提高推理速度
  • 在连续时间上训练

🙃🙃关注公众号 funNLPer 了解更多AI算法😘😘

4. 参考

  • [1]. 有真实参照的图像质量的客观评估指标:SSIM、PSNR和LPIPS
  • [2]. 图像质量评估—FID
  • [3]. REACHING 80% ZERO-SHOT ACCURACY WITH OPENCLIP: VIT-G/14 TRAINED ON LAION-2BREACHING 80% ZERO-SHOT ACCURACY WITH OPENCLIP: VIT-G/14 TRAINED ON LAION-2B
  • [4]. 文生图模型之SDXL 👍👍
  • [5]. GAN的量化评估方法——IS和FID,及其pytorch代码
  • [6]. 深入浅出完整解析Stable Diffusion XL(SDXL)核心基础知识
  • [7]. Diffusion With Offset Noise

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

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

相关文章

Redis实战:Redis的安装及简单使用

本片将介绍 Redis 的安装及简单使用 文章目录 1、Redis安装1.1、Windows下Redis的安装1.2、Linux下Redis的安装1.3、Mac下Redis的安装(使用Homebrew) 2、Redis使用2.1、启动服务端客户端2.2、Redis简单命令 3、Redis命令大全 1、Redis安装 1.1、Windows…

Redis持久化——AOF

介绍 Redis是运行在内存中的数据库,当我们关闭了Redis服务器后,内存中的数据会丢失吗? 答案是不会的,因为Redis有持久化功能,能够将内存中的数据保存到磁盘中的文件,以此来实现数据的永久保存。 在Redis中…

Spring Clould 消息队列 - RabbitMQ

视频地址:微服务(SpringCloudRabbitMQDockerRedis搜索分布式) 初识MQ-同步通讯的优缺点(P61,P62) 同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话&…

步入React正殿 - React组件设计模式

目录 扩展学习资料 高阶组件 /src/components/hoc/withTooltip.js /src/components/hoc/itemA.jsx /src/components/hoc/itemB.jsx /src/App.js 函数作为子组件【Render pprops】 函数作为子组件 /src/components/rp/itemC.jsx【父组件】 /src/components/rp/withToo…

特朗普钱包中持有的以太坊价值高达 500 万美元

根据华盛顿公民责任与道德组织最新发布的经认证的《2023年财务披露信息》,美国前总统唐纳德特朗普持有的以太坊价值高达500万美元。其中,详细条目特别列出了280万美元的收入。此外,特朗普还从NFT INT LLC的NFT授权许可协议中赚取了490万美元。…

Ubuntu系统录屏软件SimpleScreenRecorder安装及使用教程,三分钟学会!

背景:在ubuntu系统调程序时,有时需要录制实验视频,如gazebo仿真环境中机械臂的抓取视频。windows系统最好用的录屏软件非EV录屏莫属,而ubunutu系统下为我觉得SimpleScreenRecorder就很好用,下面介绍SimpleScreenRecord…

【COMP282 LEC1 and LEC2】

LEC 1 1. Printf 在C中的写法 2. Header file 1. 不能写 “.h” 2. strlen变成.size() 3. Namespace 前面用了“using namespace std;” 后面就可以直接写cout 不用写std::cout了 4. Input 就是input是std::cin >> LEC 2 1. Classes 2. 3 access modifiers in C …

美国FDA医疗器械分类目录数据库查询

最近我们在接到FDA医疗器械咨询项目时,经常收到客户关于公司产品在美国FDA医疗器械认证中或是国内所属的产品类别以及如何查询产品分类的疑问。在这里,我将为大家解答这些问题,希望能够提供帮助! 美国FDA医疗器械产品目录中包含了…

Python Opencv实践 - 图像均值滤波

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) print(img.shape) pixel_count img.shape[0] * img.shape[1] print(pixel_count)#为图像添加椒盐噪声 #参考资料&#xf…

JAVA调用外部电商API的详情步骤和注意事项

在现代电商生态中,电商API的使用变得越来越普遍。本文将为您详细介绍如何使用JAVA语言调用外部电商API的步骤,并提供一些在开发过程中需要特别注意的事项。希望通过本文的阐述,读者能够对JAVA调用外部电商API有一个全面的了解。 关键词&…

unity发布WebGL遇到的坑(持续更新)

1、unity默认字体在网页中不会显示 解决方法:自己新导入一个字体,使用导入的字体 2、之前打过包并运行过,后面又在unity中进行了修改,重新打包,运行发现还是修改之前的效果,虽然是新包, 解决方…

VTK vtkOBBTree 有向包围盒

vtkOBBTree 有向包围盒 vtkOBBTree是一个包围盒的树,它将体的每个cell分割到每个小的包围盒中,由SetNumberOfBuckets确定每个盒中放多少个 Cell。建立一个vtkOBBTree要先设定DataSet,SetDataSet。然后调用BuildLocator。包围盒精细程度由递归深度 (Max…

Linux问题--docker启动mysql时提示3306端口被占用

问题描述: 解决方法: 1.如果需要kill掉mysqld服务可以先通过 lsof -i :3306 2. 查询到占用3306的PID,随后使用 kill -15 PID 来kill掉mysqld服务。 最后结果

JDK 20下载与安装 (Windows 11系统)

JDK(Java Development Kit)是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVMJava系统类库)和JAVA工具。 JDK 20 下载 JDK 官网路径&#xff1…

内网穿透实战应用——【通过cpolar分享本地电脑上有趣的照片:发布piwigo网页】

通过cpolar分享本地电脑上有趣的照片:发布piwigo网页 文章目录 通过cpolar分享本地电脑上有趣的照片:发布piwigo网页前言1. 设定一条内网穿透数据隧道2. 与piwigo网站绑定3. 在创建隧道界面填写关键信息4. 隧道创建完成 总结 前言 首先在本地电脑上部署…

机器学习赋能乳腺癌预测:如何使用贝叶斯分级进行精确诊断?

一、引言 乳腺癌是女性最常见的恶性肿瘤之一,也会发生在男性身上。每年全球有数百万人被诊断出乳腺癌,对患者的生活和健康造成了巨大的影响。早期的乳腺癌检测和准确的诊断对于提高治疗的成功率至关重要。然而,乳腺癌的早期诊断面临着许多挑战…

[K8s]问题描述:k8s拉起来的容器少了cuda的so文件

问题解决:需要设置Runtimes:nvidia的同时设置Default Runtimenvidia

JAVA基础知识(六)——异常处理

异常 一、异常概述与异常体系结构二、常见异常三、异常处理机制一:try-catch-finally四、异常处理机制二:throws五、手动抛出异常:throw六、用户自定义异常类七、开发中如何选择使用try-catch-finally还是使用throws八、如何看待代码中的编译…

3年 Android 开发的面试心经(后悔当初没有拿 N+1)

作者:勇闯天涯 当某人顺利通过大厂面试时,总会有人认为这是运气比较好罢了,但他们不曾得知对方之前受过多少苦和委屈,又付出了多少努力一步步去突破这些困境。正是因为他们的努力付出,在合适的时间与地点,用…

Kali Linux中常用的渗透测试工具有哪些?

今天我们将继续探讨Kali Linux的应用,这次的重点是介绍Kali Linux中常用的渗透测试工具。Kali Linux作为一款专业的渗透测试发行版,拥有丰富的工具集,能够帮助安全专家和渗透测试人员检测和评估系统的安全性。 1. 常用的渗透测试工具 以下是…