【扩散模型】HuggingFace Diffusers实战

HuggingFace Diffusers实战

  • 1. 环境准备
  • 2. DreamBooth
    • 2.1 Stable Diffusion简介
    • 2.2 DreamBooth
  • 3. Diffusers核心API
  • 4. 实战:生成美丽的蝴蝶图像
    • 4.1 下载数据集
    • 4.2 调度器
    • 4.3 定义扩散模型
    • 4.4 创建扩散模型训练循环
    • 4.5 图像的生成
      • 方法1.建立一个管线
      • 方法2.写一个采样循环
  • 5. 模型上传到Hugging Face Hub
  • 6. 使用Accelerate库扩大训练模型的规模
  • 参考资料

Diffusers是用于生成图像,音频甚至分子3D结构的最先进的扩散模型的首选库。无论是寻找简单的推理解决方案还是训练自己的扩散模型,Diffusers都是一个支持两者的模块化工具箱。该library 的设计侧重于性能,简单的简单性和对抽象的可定制性。

Diffusers提供了三个核心组件:

  • 最先进的diffusion pipelines,只需几行代码就可以在推理中运行。
  • 适用于不同扩散速度和输出质量的interchangeable schedulers。
  • 可以用作构建blocks并与schedulers相结合的预训练模型,用于创建自己的端到端扩散系统。

本文学习如何使用一个功能强大的自定义扩散模型管线(pipeline),并了解如何独立制作一个新版本。学习使用Accelerate库调用多个GPU以加快模型的训练过程,并将最终模型上传到Hugging Face Hub。

1. 环境准备

安装Diffusers库:

!pip install -qq -U diffusers datasets transformers accelerate ftfy pyarrow==12.0
  • ftfy 是一个用于修复和清理 Unicode 文本的 Python 软件包。它的全称是 “fixes text for you”,意思是它可以自动检测和纠正常见的 Unicode 文本问题
    Unicode 是一种字符编码标准,用于表示文本中的字符。然而,有时文本中可能会包含一些特殊字符、编码错误、乱码或不一致的字符表示方式,这可能导致文本显示或处理上的问题。ftfy 提供了一系列功能,用于自动修复这些问题,使得文本处理更加准确和一致。通过安装 ftfy 软件包,可以在 Python 中使用它提供的函数和工具来处理和修复文本中的 Unicode 问题,从而确保文本在各种应用中的正确性和可靠性。

  • Apache Arrow是一个用于内存分析的开发平台。它包含一套技术,使大数据系统能够快速存储、处理和移动数据。它提供了一种通用的数据格式,将数据在内存中表示为表格,并支持诸如序列化和分布式读取等功能。

补充:-U就是 --upgrade,意思是如果已安装就升级到最新版;-q提供的输出较少。这个选项是加性的。换句话说,最多可以使用它3次(对应于警告、错误和关键日志记录级别)。
- -q 意味着只显示带有警告、错误、关键日志级别的消息。
- -qq 意味着只显示带有错误、关键日志级别的消息。
- -qqq 意味着只显示具有关键日志级别的消息。

然后访问https://huggingface.co/settings/tokens创建具有写权限的访问令牌
创建token
运行如下代码使用创建的访问令牌登录Huggingface:
令牌登录Huggingface
登录成功之后提示:Token is valid (permission: write).Your token has been saved in your configured git credential helpers (store).
Your token has been saved to /root/.cache/huggingface/token. Login successful

安装Git LFS以上传模型检查点

%%capture
!sudo apt -qq install git-lfs
!git config --global credential.helper store

补充:

  • **Git LFS(Large File Storage)**是由 Atlassian, GitHub 以及其他开源贡献者开发的 Git 扩展,它通过延迟地(lazily)下载大文件的相关版本来减少大文件在仓库中的影响,具体来说,大文件是在 checkout 的过程中下载的,而不是 clone 或 fetch 过程中下载的(这意味着在后台定时 fetch 远端仓库内容到本地时,并不会下载大文件内容,而是在 checkout 到工作区的时候才会真正去下载大文件的内容)。
  • %%capture: Jupyter notebook中的%%capture是一個魔術指令,它允許您捕捉單個代碼單元的輸出,以便丟棄它或將其存儲在變量中以供以後使用。例如,您可以使用%%capture防止單元格中的輸出在筆記本中顯示,或捕捉單元格的輸出並將其分配給變量。

导入依赖库:

import numpy as np
import torch
import torch.nn.functional as F
import torchvision
from matplotlib import pyplot as plt
from PIL import Image

补充:PIL(Python Imaging Library)是Pythonn中最常用的图像处理库,PIL支持图像存储、显示和处理,它能够处理几乎所有图片格式,可以完成对图像的缩放、裁剪、叠加以及图像添加线条、图像和文字等操作。根据功能的不同,PIL库共包括21个与图片相关的类,这些类可以被看做是子库或PIL库中的模块,Image是最常用的类

定义两个工具函数,用于图片展示:

def show_images(x):
  """给定一批图像,创建一个网格并将其转换为PIL"""
  x = x * 0.5 + 0.5
  grid = torchvision.utils.make_grid(x)
  grid_im = grid.detach().cpu().permute(1,2,0).clip(0,1)*255
  grid_im = Image.fromarray(np.array(grid_im).astype(np.uint8))
  return grid_im
def make_grid(images, size=64):
  """给定一个PIL图像列表,将他们叠加成一行"""
  output_im = Image.new("RGB", (size * len(images), size))
  for i, im in enumerate(images):
    output_im.paste(im.resize((size, size)), (i * size, 0))
  return output_im

查看GPU情况:
确定使用的是CUDA

2. DreamBooth

2.1 Stable Diffusion简介

Stable Diffusion,是一个 2022 年发布的文本到图像潜在扩散模型,由 CompVis、Stability AI 和 LAION 的研究人员创建的。

Stable Diffusion 技术,作为 Diffusion 改进版本,通过引入隐向量空间来解决 Diffusion 速度瓶颈,除了可专门用于文生图任务,还可以用于图生图、特定角色刻画,甚至是超分或者上色任务。

下图是一个基本的文生图流程,把中间的 Stable Diffusion 结构看成一个黑盒,那黑盒输入是一个文本串“paradise(天堂)、cosmic(广阔的)、beach(海滩)”,利用这项技术,输出了最右边符合输入要求的生成图片,图中产生了蓝天白云和一望无际的广阔海滩。
Stable Diffusion
Stable Diffusion 的核心思想是,由于每张图片满足一定规律分布,利用文本中包含的这些分布信息作为指导,把一张纯噪声的图片逐步去噪,生成一张跟文本信息匹配的图片。

2.2 DreamBooth

DreamBooth是一种个性化文生图模型:给定某个物体的几张图片作为输入,通过微调预训练的文生图模型(如Imagen),将一个独特的标识符和该物体进行绑定,这样就可以通过含有该标识符的prompt在不同场景下生成包含该物体的新颖图片。
DreamBooth
也就是说,DreamBooth能让我们对Stable Diffusion模型进行微调,并在整个过程中引入特定的面部、物体或风格的额外信息。

首先加载这个管线:
加载管线
管线加载完之后,使用以下代码生成示例图像:

# 生成示例图像
prompt = "an abstract oil painting of sks mr potato head by picasso"
image = pipe(prompt, num_inference_steps=50, guidance_scale=6.5).images[0]
image

示例图像

3. Diffusers核心API

Diffusers核心API主要分为三部分:

  • 管线:从高层次设计的多种类函数,便于部署的方式实现,能够快速利用预训练的主流扩散模型来生成样本。
  • 模型:在训练新的扩散模型时需要用到的网络结构。
  • 调度器:在推理过程中使用多种不同的技巧来从噪声中生成图像,同时可以生成训练过程中所需的"带噪"图像

示例:使用管线生成蝴蝶图像:
使用DiffuserAPI示例
结果如下:
蝴蝶图片
到目前为止,训练扩散模型的流程如下:

  1. 从训练集中加载图像。
  2. 添加不同级别的噪声
  3. 将添加了不同级别噪声的数据输入模型
  4. 评估模型对这些输入去噪的效果
  5. 使用得到的性能信息更新模型权重,然后重复上述步骤。

4. 实战:生成美丽的蝴蝶图像

4.1 下载数据集

加载一个来自Hugging Face Hub的包含1000幅蝴蝶图像的数据集。

import torchvision
from datasets import load_dataset
from torchvision import transforms

dataset = load_dataset("huggan/smithsonian_butterflies_subset", split="train")
# 也可以从本地文件夹中加载图像
#dataset = load_dataset("imagefolder", data_dir="path/to/folder")

# 将在32×32的像素的正方形图像上进行训练
image_size=32 
batch_size=64

# 定义数据增强过程
preprocess = transforms.Compose([
    transforms.Resize((image_size, image_size)),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize([0.5],[0.5])
])

def transform(examples):
  images = [preprocess(image.convert("RGB")) for image in examples["image"]]
  return {"images": images}

dataset.set_transform(transform)
train_dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)

然后从中取出一部分图像数据并可视化:
数据采样可视化

4.2 调度器

正如上文所述,在训练扩散模型中,需要获取这些输入图像并添加噪声,然后将带噪的图像输入模型。在推理阶段,使用模型的预测结果逐步消除这些噪声。在扩散模型中,这两个步骤是由调度器(scheduler)处理的。

噪声调度器能够确定在不同迭代周期分别添加多少噪声。

from diffusers import DDPMScheduler
noise_scheduler = DDPMScheduler(num_train_timesteps=1000)

基于论文“Denoising Diffusion Probabilistic Models”

通过设置beta_startbeta_endbeta_schedule 3个参数来控制噪声调度器的超参数beta

  • beta_start为控制推理阶段开始的beta值
  • beta_end为控制beta的最终值
  • beta_schedule可以通过一个函数映射来为模型推理的每一步生成一个beta值。

(1)仅添加了少量噪声

noise_scheduler = DDPMScheduler(num_train_timesteps=1000, beta_start=0.001, beta_end=0.004)

(2)cosine调度方式,这种方式可能更适合尺寸较小的图像

noise_scheduler = DDPMScheduler(num_train_timesteps=1000, beta_schedule='squaredcos_cap_v2')

无论选择哪个调度器,都可以使用noise_scheduler.add_noise为图片添加不同程度的噪声:
添加噪声

4.3 定义扩散模型

简单来说,UNet模型的工作流程如下:

  1. 输入UNet模型的图片会经过几个ResNet层中的标准网络模块,并且在经过每个标准网络模块后,图片的尺寸都将减半。
  2. 同样数量的上采样层则能够将图片的尺寸恢复到原始尺寸。
  3. 残差连接模块会将特征图分辨率相同的上采样层和下采样层连接起来。

UNet模型的一个关键特征是其输出图片的尺寸与输入图片的尺寸相同,而这正是扩散模型中所需要的。Diffusers提供了一个UNet2DModel类,用于在PyTorch中创建需要的结构。

from diffusers import UNet2DModel

# 创建模型
model = UNet2DModel(
    sample_size=image_size,
    in_channels=3,
    out_channels=3,
    layers_per_block=2,  # 每一个UNet块中的ResNet层数
    block_out_channels=(64, 128, 128, 256),
    down_block_types=(
        "DownBlock2D",
        "DownBlock2D",
        "AttnDownBlock2D",  # 带有空域维度的self-att的ResNet下采样模块
        "AttnDownBlock2D",
    ),
    up_block_types=(
        "AttnUpBlock2D",
        "AttnUpBlock2D",   # 带有空域维度的self-att的ResNet上采样模块
        "UpBlock2D",
        "UpBlock2D",
    ),
)
model.to(device);

当处理分辨率更高的图像时,尝试使用更多的上采样模块或下采样模块,并且只在分辨率最低的网络深处保留注意力模块(这是一种很特殊的网络结构,能够帮助神经网络定位特征图中最重要的部分),从而降低内存负担。

输入一批数据和随机的迭代周期数查看输出尺寸与输入尺寸是否相同:
输入和输出尺寸

4.4 创建扩散模型训练循环

在模型中逐批(batch)输入数据,并使用优化器一步一步更新模型的参数。每一批数据的训练流程如下:

  1. 随机地采样几个迭代周期
  2. 对数据进行相应的噪声处理
  3. 把”带噪“数据输入模型
  4. 把MSE作为损失函数,比较目标结果与模型的预测结果。
  5. 通过调用函数loss.backward()optimizer.step()来更新模型参数
# 设定噪声调度器
noise_scheduler = DDPMScheduler(num_train_timesteps=1000, beta_schedule="squaredcos_cap_v2")

# 训练循环
optimizer = torch.optim.AdamW(model.parameters(), lr=4e-4)
losses = []
for epoch in range(30):
  for step, batch in enumerate(train_dataloader):
    clean_images = batch["images"].to(device)
    # 为图片添加采样噪声
    noise = torch.randn(clean_images.shape).to(clean_images.device)
    bs = clean_images.shape[0]
    # 为每张图片随机采样一个时间步
    timesteps = torch.randint(0, noise_scheduler.config.num_train_timesteps, (bs, ), 
                              device=clean_images.device).long()
    # 根据每个时间步的噪声幅度,向清晰的图片中添加噪声
    noisy_images = noise_scheduler.add_noise(clean_images, noise, timesteps)
    
    # 获得模型的预测结果
    noise_pred = model(noisy_images, timesteps, return_dict=False)[0]

    # 计算损失
    loss = F.mse_loss(noise_pred, noise)
    loss.backward(loss)
    losses.append(loss.item())

    # 迭代模型参数
    optimizer.step()
    optimizer.zero_grad()
  
  if (epoch +1)%5==0:
    loss_last_epoch = sum(losses[-len(train_dataloader):])/len(train_dataloader)
    print(f"Epoch: {epoch + 1}, loss: {loss_last_epoch}")

上述代码的输出结果如下:

Epoch: 5, loss: 0.15123038180172443
Epoch: 10, loss: 0.10966242663562298
Epoch: 15, loss: 0.09312395006418228
Epoch: 20, loss: 0.08648758847266436
Epoch: 25, loss: 0.08505138801410794
Epoch: 30, loss: 0.06794926035217941

绘制损失曲线:

fig, axs = plt.subplots(1, 2, figsize=(12, 4))
axs[0].plot(losses)
axs[1].plot(np.log(losses))
plt.show()

损失曲线
另一种使用管线中模型的方法:

model = butterfly_pipeline.unet

4.5 图像的生成

方法1.建立一个管线

代码如下:
建立一个管线
将管线保存到本地文件夹中:

image_pipe.save_pretrained("my_diffusion_pipeline")

检查本地文件夹中的内容:
文件夹中的内容
scheduler与unet子文件夹包含了生成图像所需的全部组件。比如在unet子文件夹可以看到模型参数文件diffusion_pytorch_model.safetensors与描述模型结构的配置文件config.json。这两个文件包含了重建管线所需要的所有内容。可以手动将这两个文件上传到Hugging Face Hub,以便和他人共享管线,或者通过API检查代码来实现这个操作。

方法2.写一个采样循环

从完全随机的带噪图像开始,从最大噪声往最小噪声方向运行调度器并根据模型每一步的预测去去除少量噪声:
采样循环
noise_scheduler.step方法可以执行更新“样本”所需的数学运算。

5. 模型上传到Hugging Face Hub

Hugging Face Hub根据指定的模型ID来决定模型存储库的名称,代码如下:
得到模型ID
接下来,在Hugging Face Hub上创建一个模型仓库并将其上传,代码如下:
上传到Hugging Face Hub
然后还可以通过以下代码创建一个精美的模型卡片:
模型卡片
这里,我们登录Hugging Face,查看刚才上传的模型
个人模型卡片
现在通过如下代码从任何地方使用DDPMPipeline的from_pretrained方法来下载该模型:
使用上传的模型

6. 使用Accelerate库扩大训练模型的规模

Accelerate是一个库,只需添加四行代码,就可以在任何分布式配置中运行相同的PyTorch代码。简而言之,大规模的训练和推理变得简单、高效和适应性强。
下载train_unconditional
给新模型取个名字:
给模型取名字
执行以下代码,通过Accelerate库启动这个脚本。Accelerate库可以自动帮助完成诸如多GPU并行训练的训练部署功能:
accelerate加速
显然,这里报错了,通过分析错误信息,我们可以看到:This example requires a source install from HuggingFace diffusers (see https://huggingface.co/docs/diffusers/installation#install-from-source), but the version found is 0.21.4.

所以,我们要通过git clone安装diffusers源码:

!git clone https://github.com/huggingface/diffusers.git
!pip install diffusers/
!pip install -r diffusers/examples/unconditional_image_generation/requirements.txt

然后再去执行accelerate脚本:

!accelerate config
!accelerate launch train_unconditional.py \
  --dataset_name="huggan/smithsonian_butterflies_subset" \
  --resolution=64 \
  --output_dir={model_name} \
  --train_batch_size=32 \
  --num_epochs=50 \
  --gradient_accumulation_steps=1 \
  --learning_rate=1e-4 \
  --lr_warmup_steps=500 \
  --mixed_precision=no

执行结果:

Epoch 1: 100% 32/32 [00:33<00:00,  1.06s/it, loss=0.402, lr=1.28e-5, step=64]
Epoch 2: 100% 32/32 [00:31<00:00,  1.03it/s, loss=0.152, lr=1.92e-5, step=96]
Epoch 3: 100% 32/32 [00:27<00:00,  1.16it/s, loss=0.0663, lr=2.56e-5, step=128]
Epoch 4:  94% 30/32 [00:28<00:02,  1.22s/it, loss=0.0987, lr=3.16e-5, step=158]
......

然后与之前一样,把模型push到Hugging Face Hub并创建一个模型卡片:

# 把模型push到Hugging Face Hub
create_repo(hub_model_id)

api = HfApi()
api.upload_folder(
    folder_path=f"{model_name}/scheduler",
    path_in_repo="",
    repo_id=hub_model_id
)
api.upload_folder(
    folder_path=f"{model_name}/unet/", 
    path_in_repo="",
    repo_id=hub_model_id
)
api.upload_file(
    path_or_fileobj=f"{model_name}/model_index.json",
    path_in_repo="model_index.json",
    repo_id=hub_model_id
)
content=f"""
---
license: mit
tags:
- pytorch
- diffusers
- unconditional-image_generation
- diffusion-models-class
---
# 这个一个无条件图像生成扩散模型(测试),用于生成美丽的蝴蝶图像
```python
from diffusers import DDPMPipeline

pipeline=DDPMPipeline.from_pretrained('{hub_model_id}')
image = pipeline().images[0]
image

推动到Hugging Face

card=ModelCard(content)
card.push_to_hub(hub_model_id)

使用这个模型:

pipeline = DDPMPipeline.from_pretrained(hub_model_id).to(device)
images = pipeline(batch_size=8).images
make_grid(images)

在了解各种模型之前,有必须先了解下 safetensors,玩过的应该都认识,就是很多模型的后缀。然而各种模型的后缀五花八门,但是总是能看到 safetensors 的影子,让人有些缭乱。其实主要是因为 safetensors 支持各种 AI 模型,而在 safetensors 出现前,各种 AI 模型都有着自己独特的后缀。这就导致每种模型既可以使用 safetensors 又可以使用自己原有的后缀,所以入门的时候就会让人有点分不清。
其实 safetensors 是由 huggingface 研发的一种开源的模型格式,它有几种优势:

  • 足够安全,可以防止 DOS 攻击
  • 加载迅速
  • 支持懒加载
  • 通用性强

所以现在大部分的开源模型都会提供 safetensors 格式。


参考资料

  • Diffuser Github
  • PyArrow - Apache Arrow Python bindings
  • 详解 Git 大文件存储(Git LFS)
  • Jupyter notebook裡面的「%%capture」是什麼意思?
  • PIL库介绍
  • 十分钟读懂Stable Diffusion运行原理
  • DreamBooth: Fine Tuning Text-to-Image Diffusion Models for Subject-Driven Generation
  • 用AI把自己画进动漫里,3天揽获150万+播放量
  • Accelerate

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 字符集与乱码与collation设置的问题?

开头还是介绍一下群&#xff0c;如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友…

线扫相机DALSA--常见问题一:软件安装顺序

1.软件安装顺序 先安装&#xff1a;Sapera_LT_SDK&#xff0c;后安装Xtium-CL MX4驱动。 2.初次安装CamExpert&#xff0c;重启电脑后未找到相机 Settings(搜索协议)配置完毕后&#xff0c;需点击Detect Camera(一键查找相机)按钮&#xff0c;搜索相机。第一次查找相机耗时会略…

word行内插入mathtype 公式后行距变大解决办法

现象 word行内插入mathtype 公式后行距变大 解决方法 选中要进行操作的那些行&#xff0c;依次单击菜单命令“格式→段落”&#xff0c;打开“段落”对话框&#xff1b;单击“缩进和间距”选项卡&#xff0c;将间距的“段前”和“段后”都调整为“0行”&#xff1b;将“如果…

【广州华锐互动】城市水处理VR仿真实训平台

随着科技的不断发展&#xff0c;虚拟现实&#xff08;VR&#xff09;技术已经逐渐渗透到各个领域&#xff0c;为我们带来了前所未有的沉浸式体验。在教育领域&#xff0c;VR技术的应用也日益广泛&#xff0c;为传统的教学模式带来了革命性的变革。本文将以城市水处理VR仿真实训…

Java集合类--List集合,Set集合,Map集合

集合可以看作一个容器&#xff0c;Java中提供了不同的集合类&#xff0c;这些类具有不同的存储对象的方式&#xff0c;同时提供了相应的方法&#xff0c;以便用户对集合进行遍历、添加、删除、查找指定的对象。 1.集合类概述&#xff1a; 集合类类似于数组&#xff0c;与数组不…

公网远程访问macOS本地web服务器

# 公网访问macOS本地web服务器【内网穿透】 文章目录 1. 启动Apache服务器2. 公网访问本地web服务2.1 本地安装配置cpolar2.2 创建隧道2.3 测试访问公网地址3. 配置固定二级子域名3.1 保留一个二级子域名3.2 配置二级子域名4. 测试访问公网固定二级子域名 以macOS自带的Apache…

局域网内两台电脑共享文件夹(通过网线直连共享数据)

文章目录 2.设置共享文件夹3.访问共享文件夹 1.将两台电脑置于同一局域网下 用网线将两台电脑连接关闭两台电脑防火墙将两台电脑IP地址设置在同一局域网下 测试是否在同一局域网下&#xff0c;使用ping命令 ping 192.168.0.122.设置共享文件夹 选择想要共享的文件夹&#xff…

基于单片机的智能电子鼻的设计

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、智能电子鼻系统的设计方案1.1智能电子鼻系统的设计思路1.2智能电子鼻系统的设计流程图1.3智能电子鼻系统的硬件数…

Android系统的特性

目录 Android系统的特性 1. 显示布局 2. 数据存储 3. 网络 4. 信息 5. 浏览器 6. 编程语言支持 7. 媒体支持 8. 流媒体支持 9. 硬件支持 10. 多点触控 11.蓝牙 12. 多任务处理 13. 语音功能 14.无线共享功能 15. 截图功能 16. 跨平台 17. 应用程序的安全机制…

IT行业变成了夕阳行业

IT技术发展背景及历程 从2010年左右开始&#xff0c;大众创新&#xff0c;万众创业变成了一个经常看到的词语&#xff0c;在创业潮的带动下&#xff0c;同时刚好赶上了互联网的高速发展&#xff0c;一大批互联网创业公司应运而生&#xff0c;在这样的背景下&#xff0c;IT行业…

JVM进阶(3)

一)什么是垃圾&#xff1f; 垃圾指的是在应用程序中没有任何指针指向的对象&#xff0c;这个对象就是需要被回收的垃圾&#xff0c;如果不及时的针对内存中的垃圾进行清理&#xff0c;那么这些垃圾对象所占用的内存空间可能一直保留到应用程序结束&#xff0c;被保留的空间无法…

常见排序算法之冒泡排序

冒泡排序&#xff0c;英文名Bubble Sort&#xff0c;是一种相对基础的 交换排序方法。这种排序算法的名字来源于它操作的过程&#xff0c;可以类比为数列中的每一个元素都可以像小气泡一样&#xff0c;根据自身的大小一点一点向数组的一侧移动。具体到冒泡排序的工作原理&#…

即时编译器JIT

类编译加载执行过程 如下图所示&#xff0c;一个Java代码从编译到运行大抵会经历以下几个过程。具体每个过程笔者会在下文站展开讨论。 类编译 首先是类编译阶段&#xff0c;这个阶段会将Java文件变为class文件&#xff0c;这个class文件包含一个常量池和方法表集合&#xf…

Android数据对象序列化原理与应用

序列化与反序列化 序列化是将对象转换为可以存储或传输的格式的过程。在计算机科学中&#xff0c;对象通常是指内存中的数据结构&#xff0c;如数组、列表、字典等。通过序列化&#xff0c;可以将这些对象转换为字节流或文本格式&#xff0c;以便在不同的系统之间进行传输或存…

【机器学习可解释性】4.SHAP 值

机器学习可解释性 1.模型洞察的价值2.特征重要性排列3.部分依赖图4.SHAP 值5.SHAP 值 高级使用 正文 理解各自特征的预测结果&#xff1f; 介绍 您已经看到(并使用)了从机器学习模型中提取一般解释技术。但是&#xff0c;如果你想要打破模型对单个预测的工作原理? SHAP 值…

Postman —— 配置环境变量

PostMan是一套比较方便的接口测试工具&#xff0c;但我们在使用过程中&#xff0c;可能会出现创建了API请求&#xff0c;但API的URL会随着服务器IP地址的变化而改变。 这样的情况下&#xff0c;如果每一个API都重新修改URL的话那将是非常的麻烦&#xff0c;所以PostMan中也提供…

Sprint Cloud Stream整合RocketMq和websocket实现消息发布订阅

1.引入RocketMQ依赖&#xff1a;首先&#xff0c;在pom.xml文件中添加RocketMQ的依赖&#xff1a; <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.0</versi…

J2EE项目部署与发布(Windows版本)->会议OA单体项目Windows部署,spa前后端分离项目Windows部署

会议OA单体项目Windows部署spa前后端分离项目Windows部署 1.会议OA单体项目Windows部署&#xff08;以实施的角度&#xff09; 将项目放入webapp&#xff0c;项目能够访问: 首先拿到war包和数据库脚本&#xff0c;并检查是否有什么问题。 如何查看项目报错信息&#xff08;当你…

Nginx性能优化

简介 nginx作为常用的web代理服务器&#xff0c;某些场景下对于性能要求还是蛮高的&#xff0c;所以本片文章会基于操作系统调度以及网络通信两个角度来讨论一下Nginx性能的优化思路。 基于操作系统调度进行Nginx优化 CPU工作方式 对于用户进程&#xff0c;CPU会按照下面的…

深入浅出排序算法之堆排序

目录 1. 算法介绍 2. 执行流程⭐⭐⭐⭐⭐✔ 3. 代码实现 4. 性能分析 1. 算法介绍 堆是一种数据结构&#xff0c;可以把堆看成一棵完全二叉树&#xff0c;这棵完全二叉树满足&#xff1a;任何一个非叶结点的值都不大于(或不小于)其左右孩子结点的值。若父亲大孩子小&#x…
最新文章