书生大模型实训营第4期进阶岛第三关:LMDeploy 量化部署进阶实践

书生大模型实训营第4期进阶岛第三关:LMDeploy 量化部署进阶实践

    • 1. 配置 LMDeploy 环境
      • 1.1 开发机的创建与环境搭建
      • 1.2 模型获取
      • 1.3 模型测试
    • 2. InternLM2.5 的部署与量化
      • 2.1 LMDeploy API 部署 InternLM2.5
        • 2.1.1 启动API服务器
        • 2.1.2 以命令行形式连接 API 服务器
        • 2.1.3 以 Gradio 网页形式连接 API 服务器
      • 2.2 使用 LMDeploy 量化模型
        • 2.2.1 设置最大 kv cache 缓存大小
        • 2.2.2 设置在线 kv cache int4/int8 量化
        • 2.2.3 W4A16 模型量化和部署
        • 2.2.4 W4A16 量化+ KV cache 量化
    • 3. 使用 LMDeploy 量化与部署 InternVL2
      • 3.1 LMDeploy 量化 InternVL2
        • 3.1.1 W4A16 模型量化和部署
        • 3.1.2 W4A16 量化+ KV cache 量化
      • 3.2 LMDeploy API 部署 InternVL2
    • 4. LMDeploy 之 FastAPI 与 Function call
      • 4.1 API 开发
      • 4.2 Function call

1. 配置 LMDeploy 环境

1.1 开发机的创建与环境搭建

新建一个 30%A100 开发机,镜像选择 Cuda12.2-conda。

由于我们要运行参数量为 7B 的 InternLM2.5,由 InternLM2.5 的码仓查询 InternLM2.5-7b-chat 的config.json 文件可知,该模型的权重被存储为 bfloat16 格式,每个参数需要占用两个字节,因此模型的总的权重大小约为:
7 × 1 0 9 p a r a m e t e r s × 2 B y t e s / p a r a m e t e r ≈ 14 G B 7×10^9 parameters×2 Bytes / parameter \approx 14GB 7×109parameters×2 Bytes/parameter14GB这就是为什么我们要选 30%A100(24G)的配置。在终端运行以下指令创建虚拟环境:

# 创建环境
conda create -n lagent python=3.10 -y
# 激活环境
conda activate lagent
# 安装 torch
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y
# 安装其他依赖包
pip install termcolor==2.4.0
pip install streamlit==1.39.0
pip install class_registry==2.1.2
pip install datasets==3.1.0

1.2 模型获取

在 root 目录下创建一个 models 文件夹用于存放后续实验需要用到的模型,这里直接使用 share 文件夹下现成的模型即可,将这些文件夹软链接到 models 文件夹下:

mkdir /root/models
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2_5-7b-chat /root/models
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat /root/models
ln -s /root/share/new_models/OpenGVLab/InternVL2-26B /root/models

1.3 模型测试

在正式开始量化之前我们先测试一下 share 文件夹中的模型是否能够正常运行,先试一下 internlm2_5-7b-chat 模型。运行下面这条命令:

lmdeploy chat /root/models/internlm2_5-7b-chat

稍微等一会,启动成功后应该能看到下面这个界面,这时我们就能在命令行终端直接跟模型对话了:

在这里插入图片描述
在这里插入图片描述
这里注意输入完问题之后需要连续按两次回车模型才能进行回答。我让模型推荐一些适合入门的高数教材,感觉回答的还不错~

运行这个 7B 的模型显存占用情况如下:

在这里插入图片描述
差不多占了 23G 的显存,跟我们之前估计的 14G 好像不太一样?

其实这个差距是 kv-cache 的存在导致的。KV Cache(键值缓存)是一种在大模型推理中用于提升性能的优化技术。它通过缓存 Transformer 模型中 Attention 机制计算出的键(Key)和值(Value),来减少重复计算,从而提高推理速度。

上面我们估计的 14G 指的是模型的纯权重大小,如下图所示,在模型正式上显卡运行时,lmdeploy 默认设置 cache-max-entry-count 为 0.8,即 kv cache 占用剩余显存的 80%;

在这里插入图片描述
也就是说我们模型实际占用的 23G 显存应该是这么计算的:
23 G = 14 G + ( 24 G − 14 G ) ∗ 0.8 + o t h e r _ i t e m s 23G = 14G + (24G-14G) * 0.8 + other\_items 23G=14G+(24G14G)0.8+other_items除了上面这种直接看右上角资源监视器的方式,我们还可以直接通过命令行查看显存占用情况,这种方式普适性更高。这里除了经典的 nvidia-smi 命令外,书生平台还提供了 studio-smi 命令来查看显卡运行情况。我们新开一个终端分别运行看一下结果:

在这里插入图片描述
在这里插入图片描述
这里明明显卡就 24G 的显存,为什么 nvidia-smi 命令还查出来 40多G 的占用呢?这是因为实验室提供的环境为虚拟化的显存,nvidia-smi 是 NVIDIA GPU 驱动程序的一部分,用于显示 NVIDIA GPU 的当前状态,故当前环境只能看 80GB 单卡 A100 显存使用情况,无法观测虚拟化后 30% 或 50%A100 等的显存情况。针对于此,实验室提供了 studio-smi 命令工具,能够观测到虚拟化后的显存使用情况。这也是为什么两个命令的查看结果不一致。

2. InternLM2.5 的部署与量化

在上一节中我们直接在将模型部署在了本地,但是有些时候我们可能需要让别人也能使用我们的模型,这时候我们就需要将大模型封装为 API 接口服务,供客户端访问。

2.1 LMDeploy API 部署 InternLM2.5

2.1.1 启动API服务器

运行以下命令启动 API 服务器,部署 InternLM2.5 模型:

conda activate lmdeploy
lmdeploy serve api_server \/root/models/internlm2_5-7b-chat \--model-format hf \--quant-policy 0 \--server-name 0.0.0.0 \--server-port 23333 \--tp 1

稍待片刻,终端显示如下:

在这里插入图片描述

这一步由于部署在远程服务器上,所以本地需要做一下 ssh 转发才能直接访问。在本地打开一个 cmd 或 powershell 窗口,输入命令如下(端口映射教程可以参考我的 这篇文章:

 ssh -CNg -L 23333:127.0.0.1:23333 root@ssh.intern-ai.org.cn -p 你的ssh端口号

注意,如果你不是第一次做映射的话这个命令是不会有任何输出的,不要以为它卡住了

然后打开浏览器,访问 http://127.0.0.1:23333 看到如下界面即代表部署成功:

在这里插入图片描述

2.1.2 以命令行形式连接 API 服务器

关闭 http://127.0.0.1:23333 网页,但保持终端和本地窗口不动,新建一个终端,运行如下命令:

lmdeploy serve api_client http://localhost:23333

稍待片刻,等出现 double enter to end input >>> 的输入提示即启动成功,此时便就可以跟模型对话了,同样是两下回车确定,输入exit退出。

在这里插入图片描述

2.1.3 以 Gradio 网页形式连接 API 服务器

保持第一个终端不动,退出刚刚新建的终端,输入以下命令,使用 Gradio 作为前端,启动网页:

lmdeploy serve gradio http://localhost:23333 \--server-name 0.0.0.0 \--server-port 6006

出现下图所示界面就说明我们的 Gradio 服务启动了:

在这里插入图片描述
关闭之前的 cmd/powershell 窗口,重开一个,再次做一下 ssh 转发(因为此时端口不同)。在本地再打开一个 cmd/powershell 窗口,运行以下命令:

ssh -CNg -L 6006:127.0.0.1:6006 root@ssh.intern-ai.org.cn -p <你的ssh端口号>

然后打开浏览器,访问地址 http://127.0.0.1:6006,就可以与模型对话了:

在这里插入图片描述

2.2 使用 LMDeploy 量化模型

随着模型变得越来越大,我们需要一些大模型压缩技术来降低模型部署的成本,并提升模型的推理性能。LMDeploy 提供了权重量化和 kv cache 两种策略。

2.2.1 设置最大 kv cache 缓存大小

kv cache 是一种缓存技术,通过存储键值对的形式来复用计算结果,以达到提高性能和降低内存消耗的目的。在大规模训练和推理中,kv cache 可以显著减少重复计算量,从而提升模型的推理速度。理想情况下,kv cache 全部存储于显存,以加快访存速度。

模型在运行时,占用的显存可大致分为三部分:模型参数本身占用的显存、kv cache占用的显存,以及中间运算结果占用的显存。LMDeploy 的 kv cache 管理器可以通过设置 --cache-max-entry-count 参数控制 kv 缓存占用剩余显存的最大比例。默认的比例为0.8。这里我们重新设置一下这个比例再部署一遍 InternLM2.5-7B:

lmdeploy chat /root/models/internlm2_5-7b-chat --cache-max-entry-count 0.4

此时的显存占用情况:

在这里插入图片描述
可以看到,相比之前的 23G,这里减少了大概 4G 的显存占用,我们来分析一下为什么。首先模型参数还是占用 14G 不变,kv cache 因为占比从 0.8 减少为 0.4,因此其占用显存大小应为:
0.4 ∗ ( 24 G − 14 G ) = 4 G 0.4 * (24G-14G) = 4G 0.4(24G14G)=4G所以两者一共占用了 14+4=18G 的显存,再加上一些其他占用,共计约 19G。

2.2.2 设置在线 kv cache int4/int8 量化

我们以 2.1 LMDeploy API 部署 InternLM2.5 的实践为例,输入以下指令,启动 API 服务器:

lmdeploy serve api_server \/root/models/internlm2_5-7b-chat \--model-format hf \--quant-policy 4 \--cache-max-entry-count 0.4\--server-name 0.0.0.0 \--server-port 23333 \--tp 1

这里不仅设置了 kv cache 的显存占比,还修改了 --quant-policy 这个参数。LMDeploy 规定 quant_policy=4 表示 kv int4 量化,quant_policy=8 表示 kv int8 量化。模型部署完成后此时的资源占用情况如下:

在这里插入图片描述
还是 19G ?你可能会疑惑这里不是设置了 int4 量化吗,难道这个量化对显存占用没有任何优化吗?其实不然,首先你要明确的一点是,int4/int8 量化是针对 kv cache 的量化,模型权重该占多少占多少,所以除去模型自身的 14G,显卡还剩 10G 空闲空间,而这 10G 中需要划 40% 给 kv cache( --cache-max-entry-count 0.4),也就是 4G。

到这跟普通部署看起来好像一样,但是其实在设置 int4 量化后,LMDeploy 将会使用 int4 精度提前开辟 4GB 的 kv cache,这也就意味着相比于使用 BF16 精度的 kv cache,int4 量化的 Cache 在相同 4GB 的显存下可以存储的元素数量是 BF16 的四倍。如果不考虑精度的影响,这里的 4GB kv cache 空间就相当于普通的 16GB,更多的缓存键值对也就意味着更快的模型推理速度,这也是模型量化的目的所在。

2.2.3 W4A16 模型量化和部署

上面我们的量化是针对 kv cache 进行的,下面我们将对模型自身权重进行量化。

标题中的 W4A16 就是对模型权重进行量化的一种方法:

  • W4:表示将权重量化为4位整数(int4)。这意味着模型中的权重参数将从它们原始的浮点表示(例如 FP32、BF16 或 FP16)转换为4位的整数表示。这样做可以显著减少模型权重的大小。
  • A16:表示激活(或输入/输出)仍然保持16位浮点数(例如 FP16 或 BF16)表示。

因此,W4A16 的量化配置意味着将权重量化为4位整数的同时保持激活值为16位浮点数。

我们运行以下指令,对 internlm2_5-1_8b-chat 模型执行 W4A16 量化:

lmdeploy lite auto_awq \/root/models/internlm2_5-1_8b-chat \--calib-dataset 'ptb' \--calib-samples 128 \--calib-seqlen 2048 \--w-bits 4 \--w-group-size 128 \--batch-size 1 \--search-scale False \--work-dir /root/models/internlm2_5-1_8b-chat-w4a16-4bit

量化完成后我们可以输入如下指令查看量化后的模型大小:

cd /root/models/
du -sh *

在这里插入图片描述

再看一下原模型大小:

cd /root/share/new_models/Shanghai_AI_Laboratory/
du -sh *

在这里插入图片描述
3.6G 降到了 1.5 G,2.4 倍的压缩,虽然没有大体量模型效果那么明显,不过也很不错了。

我们再在本地部署一下这个量化后的模型:

lmdeploy chat /root/models/internlm2_5-1_8b-chat-w4a16-4bit/ --model-format awq

此时的显存占用情况如下:

在这里插入图片描述
原始显存占用情况如下:

在这里插入图片描述
可以看到几乎没什么变化,为什么呢?我们不是量化过了吗?

我们还是详细分析一下显存占用情况。首先量化后的模型权重大小大概只有原模型的 25%(原始权重大概是 3.35G,计算方式同 7B 模型),因此量化模型的权重占用约为 3.35/4=0.84G,这里我们没有额外设置 kv cache,因此还是按照默认 0.8,所以 kv cache 占用显存为:(24-0.84)*0.8=18.3G,所以模型权重+ kv cache 一共约占 18.3 + 0.84 = 19.14G,再加上其他的一些占用,差不多就是 20G 的样子。

从这里我们可以看出,虽然整体显存占用没什么区别,但是量化后的模型腾出了更多的 kv cache 空间,这也就意味着我们模型后续的推理会更快。

2.2.4 W4A16 量化+ KV cache 量化

既然 W4A16 和 KV cache 量化分别是针对显存占用的不同部分进行优化,那理论上这两种优化方法是可以一起执行的,LMDeploy 中也提供了对应的方法支持。我们只需要在部署量化后的 W4A16 模型时设置 quant-policy 参数即可。比如我们可以拿 2.2.3 中量化后的模型来试一下:

lmdeploy serve api_server \/root/models/internlm2_5-1_8b-chat-w4a16-4bit/ \--model-format awq \--quant-policy 4 \--cache-max-entry-count 0.4\--server-name 0.0.0.0 \--server-port 23333 \--tp 1

然后我们再观察我们的显存占用情况:

在这里插入图片描述

可以看到这下差距就明显了,11G 对 20G,老规矩,还是分析一波。首先量化后的模型权重约占 0.84G,部署时设置 kv cache 占比 40%,所以 kv cache 占用显存:(24-0.84)*0.4=9.26G,加起来一共 10.1G,然后加上一些其他占用,差不多就是 11G 了。

3. 使用 LMDeploy 量化与部署 InternVL2

3.1 LMDeploy 量化 InternVL2

3.1.1 W4A16 模型量化和部署

这里 26B 的太大了,为了减少量化的时间,我选择量化 2B 的模型。在量化之前先运行这条命令将 share 文件夹下的 InternVL2-2B 模型软链接出来:

ln -s /root/share/new_models/OpenGVLab/InternVL2-2B /root/models

然后执行量化命令:

conda activate lmdeploy
lmdeploy lite auto_awq \/root/models/InternVL2-2B \--calib-dataset 'ptb' \--calib-samples 128 \--calib-seqlen 2048 \--w-bits 4 \--w-group-size 128 \--batch-size 1 \--search-scale False \--work-dir /root/models/InternVL2-2B-w4a16-4bit

出现这个界面就说明量化开始了:

在这里插入图片描述
推理结束后就能在 models 文件夹下看到量化后的模型配置文件:

在这里插入图片描述

注意:这里如果量化时出现如下报错:

在这里插入图片描述
那这大概率是你 transformer 库的版本不对,换成 4.37.2 就行。

3.1.2 W4A16 量化+ KV cache 量化

运行下面的命令启用量化后的模型:

lmdeploy serve api_server \/root/models/InternVL2-2B-w4a16-4bit \--model-format awq \--quant-policy 4 \--cache-max-entry-count 0.1\--server-name 0.0.0.0 \--server-port 23333 \--tp 1

启动后观测显存占用情况:

在这里插入图片描述
可以看到,5.2G 就拿下了。老规矩,我们还是来计算一下显存的具体占用分配。

从 官方文档 得知,InternVL2 2B 是由一个 304M 的 ViT、一个 12.6M 的 MLP 以及一个 2.21B 的internlm 组成的:

在这里插入图片描述

因此我们显存的占用分析分为四部分进行:

  1. ViT 占用:在 fp16 精度下,304M ViT 模型权重占用 0.6GB ( ViT 使用精度为 fp16 的 pytorch 推理,量化只对 internlm 起效果)
  2. internlm 占用:在 int4 精度下,2.21B 的 internlm 模型权重占用 4.4GB / 4 = 1.1GB
  3. kv cache占用: (24-0.6-1.1) * 0.1 = 2.23GB
  4. 其他项占用:1.27GB

因此 5.2GB = Vit 权重占用 0.6GB + internlm 模型权重占用 1.1GB + kv cache 占用 2.23GB + 其他项1.27GB

3.2 LMDeploy API 部署 InternVL2

具体封装操作与之前大同小异,还是先通过以下命令启动 API 服务器,部署量化后的 InternVL2-2B 模型:

lmdeploy serve api_server \/root/models/InternVL2-2B-w4a16-4bit/ \--model-format awq \--quant-policy 4 \--cache-max-entry-count 0.1 \--server-name 0.0.0.0 \--server-port 23333 \--tp 1

其余步骤(命令行形式、Gradio网页形式连接操作)与 2.1.1 中完全一致。

以下为 Gradio 网页形式连接成功后对话截图:

在这里插入图片描述

4. LMDeploy 之 FastAPI 与 Function call

前面我们均是借助 FastAPI 封装一个 API 出来让 LMDeploy 自行进行访问,而基于这个封装出来的 API ,我们还进行更加灵活更具 DIY 的开发。

4.1 API 开发

还是先启动 API 服务器:

conda activate lmdeploy
lmdeploy serve api_server \/root/models/internlm2_5-1_8b-chat-w4a16-4bit \--model-format awq \--cache-max-entry-count 0.4 \--quant-policy 4 \--server-name 0.0.0.0 \--server-port 23333 \--tp 1

然后新建一个终端,在终端中使用 touch 命令创建一个 internlm2_5.py 文件:

touch /root/internlm2_5.py

然后将以下内容复制粘贴进 internlm2_5.py:

# 导入openai模块中的OpenAI类,这个类用于与OpenAI API进行交互
from openai import OpenAI# 创建一个OpenAI的客户端实例,需要传入API密钥和API的基础URL
client = OpenAI(api_key='YOUR_API_KEY',  # 替换为你的OpenAI API密钥,由于我们使用的本地API,无需密钥,任意填写即可base_url="http://0.0.0.0:23333/v1"  # 指定API的基础URL,这里使用了本地地址和端口
)# 调用client.models.list()方法获取所有可用的模型,并选择第一个模型的ID
# models.list()返回一个模型列表,每个模型都有一个id属性
model_name = client.models.list().data[0].id# 使用client.chat.completions.create()方法创建一个聊天补全请求
# 这个方法需要传入多个参数来指定请求的细节
response = client.chat.completions.create(model=model_name,  # 指定要使用的模型IDmessages=[  # 定义消息列表,列表中的每个字典代表一个消息{"role": "system", "content": "你是一个友好的小助手,负责解决问题."},  # 系统消息,定义助手的行为{"role": "user", "content": "帮我讲述一个关于狐狸和西瓜的小故事"},  # 用户消息,询问时间管理的建议],temperature=0.8,  # 控制生成文本的随机性,值越高生成的文本越随机top_p=0.8  # 控制生成文本的多样性,值越高生成的文本越多样
)# 打印出API的响应结果
print(response.choices[0].message.content)

这份代码的作用就是调用 LMDeploy 封装的 API 来与模型进行一次对话。执行下面这条命令运行一下这个程序:

python /root/internlm2_5.py

正常运行后终端会输出如下结果:

在这里插入图片描述

4.2 Function call

Function call,即函数调用功能,它允许开发者在调用模型时,详细说明函数的作用,并使模型能够智能地根据用户的提问来输入参数并执行函数。完成调用后,模型会将函数的输出结果作为回答用户问题的依据。

目前 LMDeploy 在 0.5.3 版本中支持了对 InternLM2、InternLM2.5 和 llama3.1 这三个模型,故我们选用 InternLM2.5 封装API。先启动 API 服务:

conda activate lmdeploy
lmdeploy serve api_server \/root/models/internlm2_5-7b-chat \--model-format hf \--quant-policy 0 \--server-name 0.0.0.0 \--server-port 23333 \--tp 1

新建一个终端,使用 touch 命令创建一个 internlm2_5_func.py 文件:

touch /root/internlm2_5_func.py

然后将以下内容复制粘贴进 internlm2_5_func.py 中:

from openai import OpenAIdef add(a: int, b: int):return a + bdef mul(a: int, b: int):return a * btools = [{'type': 'function','function': {'name': 'add','description': 'Compute the sum of two numbers','parameters': {'type': 'object','properties': {'a': {'type': 'int','description': 'A number',},'b': {'type': 'int','description': 'A number',},},'required': ['a', 'b'],},}
}, {'type': 'function','function': {'name': 'mul','description': 'Calculate the product of two numbers','parameters': {'type': 'object','properties': {'a': {'type': 'int','description': 'A number',},'b': {'type': 'int','description': 'A number',},},'required': ['a', 'b'],},}
}]
messages = [{'role': 'user', 'content': 'Compute (3+5)*2'}]client = OpenAI(api_key='YOUR_API_KEY', base_url='http://0.0.0.0:23333/v1')
model_name = client.models.list().data[0].id
response = client.chat.completions.create(model=model_name,messages=messages,temperature=0.8,top_p=0.8,stream=False,tools=tools)
print(response)
func1_name = response.choices[0].message.tool_calls[0].function.name
func1_args = response.choices[0].message.tool_calls[0].function.arguments
func1_out = eval(f'{func1_name}(**{func1_args})')
print(func1_out)messages.append({'role': 'assistant','content': response.choices[0].message.content
})
messages.append({'role': 'environment','content': f'3+5={func1_out}','name': 'plugin'
})
response = client.chat.completions.create(model=model_name,messages=messages,temperature=0.8,top_p=0.8,stream=False,tools=tools)
print(response)
func2_name = response.choices[0].message.tool_calls[0].function.name
func2_args = response.choices[0].message.tool_calls[0].function.arguments
func2_out = eval(f'{func2_name}(**{func2_args})')
print(func2_out)

运行该 python 代码:

python /root/internlm2_5_func.py

最终得到模型输出如下:

在这里插入图片描述

可以看到,模型将输入 'Compute (3+5)*2' 根据提供的 function 拆分成了"加"和"乘"两步,第一步调用 function add 实现加,再于第二步调用 function mul 实现乘,再最终输出结果16。

这里如果运行报错记得检查下自己的 lmdeploy 版本,确保为 0.5.3

至此,书生大模型实训营第4期进阶岛第三关任务完成~

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

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

相关文章

visionpro官方示例分析(一) 模板匹配工具 缺陷检测工具

1.需求&#xff1a;找出图像中的这个图形。 2.步骤 使用CogPMAlignTool工具&#xff0c;该工具是模板匹配工具&#xff0c;见名知意&#xff0c;所谓模板匹配工具就是说先使用该工具对一张图像建立模板&#xff0c;然后用这个模板在其他图像上进行匹配&#xff0c;匹配上了就说…

Z2400027基于Java+SpringBoot+Mysql+thymeleaf引擎的图书馆管理系统的设计与实现 代码 论文

图书馆管理系统的设计与实现 一、项目背景与简介二、系统总体功能三、运行环境与技术选型四、系统架构与模块划分五、系统界面截图六、源码获取 一、项目背景与简介 项目背景&#xff1a; 随着信息技术的不断发展和图书资源的日益丰富&#xff0c;图书馆作为知识传播和学习的重…

详谈面试题:Vue、React为什么使用虚拟DOM

虚拟DOM是一种在前端框架中广泛使用的技术&#xff0c;它可以提升开发效率。那么国外流行的框架svelte没有使用虚拟DOM&#xff0c;而是直接操作真实DOM&#xff0c;效率依然很高。为什么Vue和React不采用这种方式呢&#xff1f; 目录 一、框架设计 二、解耦运行环境 三、总…

Next.js-样式处理

#题引&#xff1a;我认为跟着官方文档学习不会走歪路 Next.js 支持多种为应用程序添加样式的方法&#xff0c;包括&#xff1a; CSS Modules&#xff1a;创建局部作用域的 CSS 类&#xff0c;避免命名冲突并提高可维护性。全局 CSS&#xff1a;使用简单&#xff0c;对于有传统…

神经网络中的损失函数(Loss Function)

损失函数&#xff08;Loss Function&#xff09;在机器学习和深度学习中扮演着至关重要的角色&#xff0c;它是衡量模型预测值与实际值之间差异程度的函数。通过最小化损失函数&#xff0c;我们可以优化模型的参数&#xff0c;使其预测结果更加准确。 一、损失函数的定义 损失函…

AWS账户是否支持区域划分?

在云计算的世界中&#xff0c;亚马逊网络服务&#xff08;AWS&#xff09;凭借其全球化的基础设施和丰富的服务选项受到许多企业和开发者的青睐。一个常见的问题是&#xff1a;AWS账户是否支持区域划分&#xff1f;为了回答这个问题&#xff0c;我们九河云一起深入了解AWS的区域…

鼠标前进后退键改双击,键盘映射(AutoHotkey)

初衷&#xff1a; 1.大部分鼠标为不可自定义按键&#xff0c;可以自定义的又很贵。 鼠标左键是双击是很频类很高的操作&#xff0c;鼠标前进/后退按键个人感觉使用频率很低&#xff0c;因此把鼠标前进/后退改为双击还是很合适的。 2.有些短款的键盘没有Home或End键&#xff0c;…

华为海思2025届校招笔试面试经验分享

目前如果秋招还没有offer的同学&#xff0c;可以赶紧投递下面这些公司&#xff0c;都在补招。争取大家年前就把后端offer拿下。如果大家在准备秋招补录取过程中有任何问题&#xff0c;都可以私信小编&#xff0c;免费提供帮助。如果还有部分准备备战春招的同学&#xff0c;也可…

Springboot项目搭建(7)-Layout界面布局

1.概要 初步搭建了Layout界面的布局&#xff0c;其中包括左侧导航栏及其路由功能&#xff0c;和右侧头、体、脚部分的大致排版。最后在头部分中的昵称与头像替换成动态数据。 2.Layout主页布局 文件地址&#xff1a;src\views\Layout.vue 2.1 script行为模块 从elementUI中…

c语言的qsort函数理解与使用

介绍&#xff1a;qsort 函数是 C 标准库中用于排序的快速排序算法函数。它的用法非常灵活&#xff0c;可以对任意类型的元素进行排序&#xff0c;只要提供了比较函数即可。 qsort 函数原型及参数解释&#xff1a; void qsort ( void* base, //指向要排序的数组的首元素…

#渗透测试#红蓝攻防#HW#漏洞挖掘#漏洞复现01-笑脸漏洞(vsftpd)

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

(73)脉冲幅度调制PAM调制解调通信系统的MATLAB仿真

文章目录 前言一、PAM调制的基本原理二、PAM调制的步骤三、PAM调制示例四、PAM调制的应用五、MATLAB仿真1. 仿真代码2. 仿真结果 总结 前言 PAM&#xff08;Pulse Amplitude Modulation&#xff0c;脉冲振幅调制&#xff09;是一种模拟信号到数字信号的转换方式&#xff0c;它…

算法的NPU终端移植:深入探讨与实践指南

目录 ​编辑 引言 算法选择 模型压缩 权重剪枝 量化 知识蒸馏 硬件适配 指令集适配 内存管理 并行计算 性能测试 速度测试 精度测试 功耗测试 案例分析 图像识别算法的NPU移植案例 结论 引言 在人工智能技术的浪潮中&#xff0c;神经网络处理器&#xff08;…

汽车免拆诊断案例 | 2017款捷豹F-PACE车发动机偶尔怠速不稳

故障现象  一辆2017款捷豹F-PACE车&#xff0c;搭载2.0 L GTDi发动机&#xff0c;累计行驶里程约为16万km。车主反映&#xff0c;车辆组合仪表上发动机故障灯点亮&#xff08;图1&#xff09;&#xff0c;且发动机偶尔怠速不稳。 图1 发动机故障灯点亮 故障诊断 接车后试车…

不建模,无代码,如何快速搭建VR虚拟展厅?

不建模、无代码搭建虚拟展厅&#xff0c;可以借助一些专业的虚拟展厅搭建平台或工具来实现。以下是一些具体的步骤和建议&#xff1a; 一、选择平台或工具 首先&#xff0c;需要选择一个适合的平台或工具来搭建虚拟展厅。这些平台通常提供预设的展厅模板、拖拽式编辑工具和丰富…

数星星 (C++ 树状数组)

1265. 数星星 - AcWing题库 分析&#xff1a; 星星是按纵坐标递增给我们的&#xff0c;如果纵坐标相同&#xff0c;就按横坐标来给 所以星星是从低到高&#xff0c;一行一行来给的 题目要求我们去求每个等级的星星各有多少个 星星的等级由它左下角&#xff08;包括左边和下…

AIGC培训讲师人工智能培训讲师叶梓Python深度学习与AIGC培训提纲

【课程时长】 8天&#xff08;6小时/天&#xff09; 【课程简介】 随着AIGC&#xff08;基于AI的内容生成&#xff09;技术的崛起&#xff0c;以ChatGPT为代表的人工智能技术正引领全球科技潮流。为了帮助学员更好地理解和应用这一技术&#xff0c;特推出了本课程。 本课程…

GB28181系列三:SIP消息格式

我的音视频/流媒体开源项目(github) GB28181系列目录 目录 一、SIP消息Header字段 二、SIP URI(URL) 三、SIP路由机制 1、路由机制介绍 2、严格路由&#xff08;Strict Routing&#xff09;与松散路由&#xff08;Louse Routing&#xff09; 3、总结 四、SIP消…

STM32-C语言基础知识

C语言基础知识 stdint.h简介 给寄存器某个位赋值 给位6赋值为1流程&#xff1a;先清0&#xff0c;再赋值 带参数的宏定义 建议使用do {…}while(0)来构造宏定义 条件编译 条件编译后面必须跟宏语句&#xff0c;如#if _LED_H 指针使用常见的2大问题 1、未初始化 2、越界使…

计算机网络 实验八 应用层相关协议分析

一、实验目的 熟悉CMailServer邮件服务软件和Outlook Express客户端软件的基本配置与使用&#xff1b;分析SMTP及POP3协议报文格式和SMTP及POP3协议的工作过程。 二、实验原理 为了观察到邮件发送的全部过程&#xff0c;需要在本地计算机上配置邮件服务器和客户代理。在这里我…