LLM大模型权重量化实战

news2024/11/16 1:41:33

大型语言模型 (LLM) 以其广泛的计算要求而闻名。 通常,模型的大小是通过将参数数量(大小)乘以这些值的精度(数据类型)来计算的。 然而,为了节省内存,可以通过称为量化的过程使用较低精度的数据类型来存储权重。

我们在文献中区分了两个主要的权重量化技术:

  • 训练后量化 (PTQ:Post-Training Quantization) 是一种简单的技术,其中已训练模型的权重将转换为较低的精度,而无需任何重新训练。 尽管易于实施,但 PTQ 会导致潜在的性能下降。
  • 量化感知训练(QAT:Quantization-Aware Training)在预训练或微调阶段结合了权重转换过程,从而提高了模型性能。 然而,QAT 的计算成本很高,并且需要有代表性的训练数据。

在本文中,我们重点关注 PTQ 来降低参数的精度。 为了获得良好的直觉,我们将使用 GPT-2 模型将简单的和更复杂的技术应用于玩具示例。

整个代码可以在 Google Colab 和 GitHub 上免费获得。

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 

1、浮点数表示

数据类型的选择决定了所需的计算资源的数量,从而影响模型的速度和效率。 在深度学习应用中,平衡精度和计算性能成为一项至关重要的练习,因为更高的精度通常意味着更大的计算需求。

在各种数据类型中,浮点数主要用于深度学习,因为它们能够以高精度表示各种值。 通常,浮点数使用 n 位来存储数值。 这 n 位进一步分为三个不同的组成部分:

  • 符号(Sign):符号位表示数字的正数或负数。 它使用一位,其中 0 表示正数,1 表示负数。
  • 指数(Exponent):指数是一段位,表示基数(在二进制表示中通常为 2)的幂。 指数也可以是正数或负数,允许数字表示非常大或非常小的值。
  • 有效数/尾数(Significand/Mantissa):剩余位用于存储有效数,也称为尾数。 这代表数字的有效数字。 数字的精度在很大程度上取决于有效数字的长度。

这种设计允许浮点数以不同的精度级别覆盖广泛的值。 用于这种表示的公式是:

为了更好地理解这一点,让我们深入研究深度学习中一些最常用的数据类型:float32 (FP32)、float16 (FP16) 和 bfloat16 (BF16):

  • FP32 使用 32 位来表示数字:1位表示符号,8位表示指数,其余 23 位表示有效数。 虽然 FP32 提供高精度,但其缺点是计算量和内存占用量较高。

  • FP16 使用 16 位来存储数字:1位用于符号,5位用于指数,10位用于有效数。 尽管这使其内存效率更高并加速计算,但范围和精度的降低可能会导致数值不稳定,从而可能影响模型的准确性。

  • BF16 也是一种 16 位格式,但其中1位用于符号,8位用于指数,7位用于有效数。 与 FP16 相比,BF16 扩大了可表示范围,从而降低了下溢和上溢风险。 尽管由于有效位数较少而导致精度降低,但 BF16 通常不会显着影响模型性能,并且对于深度学习任务来说是一个有用的折衷方案。

在机器学习术语中,FP32 通常被称为“全精度”(4 字节),而 BF16 和 FP16 则被称为“半精度”(2 字节)。 但是我们可以做得更好并使用单个字节存储权重吗? 答案是 INT8 数据类型,它由能够存储 2⁸ = 256 个不同值的 8 位表示组成。 在下一节中,我们将了解如何将 FP32 权重转换为 INT8 格式。

2、朴素的8 位量化

在本节中,我们将实现两种量化技术:一种具有绝对最大 (absmax) 量化的对称技术和一种具有零点(zeropoint)量化的非对称技术。 在这两种情况下,目标都是将 FP32 张量 X(原始权重)映射到 INT8 张量 X_quant(量化权重)。

通过 absmax 量化,原始数字除以张量的绝对最大值,并乘以缩放因子 (127),以将输入映射到范围 [-127, 127]。 为了检索原始 FP16 值,将 INT8 数字除以量化因子,承认由于舍入而造成的一些精度损失。

例如,假设我们的绝对最大值为 3.2。 权重 0.1 将被量化为 round(0.1 × 127/3.2) = 4。如果我们想对其进行反量化,我们将得到 4 × 3.2/127 = 0.1008,这意味着误差为 0.008。 下面是相应的 Python 实现:

import torch

def absmax_quantize(X):
    # Calculate scale
    scale = 127 / torch.max(torch.abs(X))

    # Quantize
    X_quant = (scale * X).round()

    # Dequantize
    X_dequant = X_quant / scale

    return X_quant.to(torch.int8), X_dequant

通过零点量化,我们可以考虑不对称输入分布,例如,当考虑 ReLU 函数的输出(仅正值)时,这非常有用。 输入值首先按值的总范围 (255) 除以最大值和最小值之差进行缩放。 然后将该分布移动零点,将其映射到范围 [-128, 127](注意与 absmax 相比的额外值)。 首先,我们计算比例因子和零点值:

然后,我们可以使用这些变量来量化或反量化我们的权重:

举个例子:最大值为 3.2,最小值为 -3.0。 我们可以计算出比例为 255/(3.2 + 3.0) = 41.13,零点 -round(41.13 × -3.0) - 128 = 123 -128 = -5,因此我们之前的权重 0.1 将被量化为 round( 41.13 × 0.1 -5) = -1。 这与之前使用 absmax 获得的值(4 与 -1)有很大不同。

Python 的实现非常简单:

def zeropoint_quantize(X):
    # Calculate value range (denominator)
    x_range = torch.max(X) - torch.min(X)
    x_range = 1 if x_range == 0 else x_range

    # Calculate scale
    scale = 255 / x_range

    # Shift by zero-point
    zeropoint = (-scale * torch.min(X) - 128).round()

    # Scale and round the inputs
    X_quant = torch.clip((X * scale + zeropoint).round(), -128, 127)

    # Dequantize
    X_dequant = (X_quant - zeropoint) / scale

    return X_quant.to(torch.int8), X_dequant

借助 Transformer 库,我们可以在真实模型上使用这两个函数,而不是依赖完整的玩具示例。

我们首先加载 GPT-2 的模型和标记器。 这是一个非常小的模型,我们可能不想量化,但对于本教程来说它已经足够了。 首先,我们想要观察模型的大小,以便稍后进行比较并评估 8 位量化带来的内存节省。

!pip install -q bitsandbytes>=0.39.0
!pip install -q git+https://github.com/huggingface/accelerate.git
!pip install -q git+https://github.com/huggingface/transformers.git
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
torch.manual_seed(0)

# Set device to CPU for now
device = 'cpu'

# Load model and tokenizer
model_id = 'gpt2'
model = AutoModelForCausalLM.from_pretrained(model_id).to(device)
tokenizer = AutoTokenizer.from_pretrained(model_id)

# Print model size
print(f"Model size: {model.get_memory_footprint():,} bytes")
Model size: 510,342,192 bytes

GPT-2 模型的大小在 FP32 中约为 487MB。 下一步包括使用零点和绝对最大量化来量化权重。 在下面的示例中,我们将这些技术应用于 GPT-2 的第一个注意力层以查看结果。

# Extract weights of the first layer
weights = model.transformer.h[0].attn.c_attn.weight.data
print("Original weights:")
print(weights)

# Quantize layer using absmax quantization
weights_abs_quant, _ = absmax_quantize(weights)
print("\nAbsmax quantized weights:")
print(weights_abs_quant)

# Quantize layer using absmax quantization
weights_zp_quant, _ = zeropoint_quantize(weights)
print("\nZero-point quantized weights:")
print(weights_zp_quant)

输出结果如下:

Original weights:
tensor([[-0.4738, -0.2614, -0.0978,  ...,  0.0513, -0.0584,  0.0250],
        [ 0.0874,  0.1473,  0.2387,  ..., -0.0525, -0.0113, -0.0156],
        [ 0.0039,  0.0695,  0.3668,  ...,  0.1143,  0.0363, -0.0318],
        ...,
        [-0.2592, -0.0164,  0.1991,  ...,  0.0095, -0.0516,  0.0319],
        [ 0.1517,  0.2170,  0.1043,  ...,  0.0293, -0.0429, -0.0475],
        [-0.4100, -0.1924, -0.2400,  ..., -0.0046,  0.0070,  0.0198]])

Absmax quantized weights:
tensor([[-21, -12,  -4,  ...,   2,  -3,   1],
        [  4,   7,  11,  ...,  -2,  -1,  -1],
        [  0,   3,  16,  ...,   5,   2,  -1],
        ...,
        [-12,  -1,   9,  ...,   0,  -2,   1],
        [  7,  10,   5,  ...,   1,  -2,  -2],
        [-18,  -9, -11,  ...,   0,   0,   1]], dtype=torch.int8)

Zero-point quantized weights:
tensor([[-20, -11,  -3,  ...,   3,  -2,   2],
        [  5,   8,  12,  ...,  -1,   0,   0],
        [  1,   4,  18,  ...,   6,   3,   0],
        ...,
        [-11,   0,  10,  ...,   1,  -1,   2],
        [  8,  11,   6,  ...,   2,  -1,  -1],
        [-18,  -8, -10,  ...,   1,   1,   2]], dtype=torch.int8)

原始值 (FP32) 和量化值 (INT8) 之间的差异很明显,但 absmax 和零点权重之间的差异更为微妙。 在这种情况下,输入看起来偏移了 -1 值。 这表明该层的权重分布非常对称。

我们可以通过量化 GPT-2 中的每一层(线性层、注意力层等)来比较这些技术,并创建两个新模型:model_abs 和 model_zp。 准确地说,我们实际上会用去量化的权重替换原始权重。 这有两个好处:它允许我们:1) 比较权重的分布(相同比例)和 2) 实际运行模型。

事实上,PyTorch 默认情况下不允许 INT8 矩阵乘法。 在实际场景中,我们会对它们进行反量化以运行模型(例如在 FP16 中),但将它们存储为 INT8。 在下一节中,我们将使用bitsandbytes库来解决这个问题。

import numpy as np
from copy import deepcopy

# Store original weights
weights = [param.data.clone() for param in model.parameters()]

# Create model to quantize
model_abs = deepcopy(model)

# Quantize all model weights
weights_abs = []
for param in model_abs.parameters():
    _, dequantized = absmax_quantize(param.data)
    param.data = dequantized
    weights_abs.append(dequantized)

# Create model to quantize
model_zp = deepcopy(model)

# Quantize all model weights
weights_zp = []
for param in model_zp.parameters():
    _, dequantized = zeropoint_quantize(param.data)
    param.data = dequantized
    weights_zp.append(dequantized)

现在我们的模型已经量化,我们想要检查这个过程的影响。 直观上,我们希望确保量化后的权重接近原始权重。 检查它的一种直观方法是绘制反量化权重和原始权重的分布。 如果量化是有损的,则会极大地改变权重分布。

下图显示了这种比较,其中蓝色直方图代表原始(FP32)权重,红色直方图代表反量化(来自 INT8)权重。 请注意,我们仅显示 -2 和 2 之间的图,因为异常值的绝对值非常高(稍后会详细介绍)。

两个图都非常相似,在 0 附近有一个令人惊讶的峰值。这个峰值表明我们的量化是相当有损的,因为反转过程不会输出原始值。 对于 absmax 模型尤其如此,该模型在 0 附近显示较低的谷值和较高的峰值。

让我们比较原始模型和量化模型的性能。 为此,我们定义了一个generate_text()函数来通过top-k采样生成50个token。

def generate_text(model, input_text, max_length=50):
    input_ids = tokenizer.encode(input_text, return_tensors='pt').to(device)
    output = model.generate(inputs=input_ids,
                            max_length=max_length,
                            do_sample=True,
                            top_k=30,
                            pad_token_id=tokenizer.eos_token_id,
                            attention_mask=input_ids.new_ones(input_ids.shape))
    return tokenizer.decode(output[0], skip_special_tokens=True)

# Generate text with original and quantized models
original_text = generate_text(model, "I have a dream")
absmax_text   = generate_text(model_abs, "I have a dream")
zp_text       = generate_text(model_zp, "I have a dream")

print(f"Original model:\n{original_text}")
print("-" * 50)
print(f"Absmax model:\n{absmax_text}")
print("-" * 50)
print(f"Zeropoint model:\n{zp_text}")

输出结果如下:

Original model:
I have a dream, and it is a dream I believe I would get to live in my future. I love my mother, and there was that one time I had been told that my family wasn't even that strong. And then I got the
--------------------------------------------------
Absmax model:
I have a dream to find out the origin of her hair. She loves it. But there's no way you could be honest about how her hair is made. She must be crazy.

We found a photo of the hairstyle posted on
--------------------------------------------------
Zeropoint model:
I have a dream of creating two full-time jobs in America—one for people with mental health issues, and one for people who do not suffer from mental illness—or at least have an employment and family history of substance abuse, to work part

我们可以通过计算每个输出的困惑度(perplexity)来量化它,而不是试图查看一个输出是否比其他输出更有意义。 这是用于评估语言模型的常用指标,它衡量模型在预测序列中下一个标记时的不确定性。 在此比较中,我们做出共同的假设:分数越低,模型越好。 实际上,一个高度困惑的句子也可能是正确的。

我们使用最小函数来实现它,因为我们的句子很短,所以不需要考虑诸如上下文窗口的长度之类的细节。

def calculate_perplexity(model, text):
    # Encode the text
    encodings = tokenizer(text, return_tensors='pt').to(device)

    # Define input_ids and target_ids
    input_ids = encodings.input_ids
    target_ids = input_ids.clone()

    with torch.no_grad():
        outputs = model(input_ids, labels=target_ids)

    # Loss calculation
    neg_log_likelihood = outputs.loss

    # Perplexity calculation
    ppl = torch.exp(neg_log_likelihood)

    return ppl

ppl     = calculate_perplexity(model, original_text)
ppl_abs = calculate_perplexity(model_abs, absmax_text)
ppl_zp  = calculate_perplexity(model_zp, absmax_text)

print(f"Original perplexity:  {ppl.item():.2f}")
print(f"Absmax perplexity:    {ppl_abs.item():.2f}")
print(f"Zeropoint perplexity: {ppl_zp.item():.2f}")

输出结果如下:

Original perplexity:  15.53
Absmax perplexity:    17.92
Zeropoint perplexity: 17.97

我们看到原始模型的困惑度略低于其他两个模型。 单个实验不太可靠,但我们可以多次重复此过程以查看每个模型之间的差异。 理论上,零点量化应该比absmax稍好,但计算成本也更高。

在此示例中,我们将量化技术应用于整个层(基于每个张量)。 但是,我们可以将其应用到不同的粒度级别:从整个模型到单个值。 一次性量化整个模型会严重降低性能,而量化单个值会产生很大的开销。 在实践中,我们通常更喜欢向量量化,它考虑同一张量内的行和列中值的可变性。

然而,即使向量量化也不能解决离群特征的问题。 异常值特征是当模型达到一定规模(>6.7B 参数)时出现在所有 Transformer 层中的极值(负或正)。 这是一个问题,因为单个异常值可能会降低所有其他值的精度。 但放弃这些异常特征并不是一个选择,因为它会大大降低模型的性能。

3、使用 LLM.int8() 进行 8 位量化

由 Dettmers 等人提出, LLM.int8() 是异常值问题的解决方案。 它依赖于矢量方式(absmax)量化方案并引入混合精度量化。 这意味着异常值特征以 FP16 格式处理以保持其精度,而其他值以 INT8 格式处理。 由于异常值约占值的 0.1%,这有效地将 LLM 的内存占用量减少了近 2 倍。

LLM.int8() 的工作原理是通过三个关键步骤进行矩阵乘法计算:

  • 使用自定义阈值从输入隐藏状态 X 中提取包含异常值特征的列。
  • 使用 FP16 执行异常值的矩阵乘法,使用 INT8 执行非异常值的矩阵乘法,并进行向量量化(隐藏状态 X 为行式,权重矩阵 W 为列式)。
  • 对非异常值结果(INT8 到 FP16)进行反量化,并将其添加到异常值结果中,以获得 FP16 中的完整结果。

这种方法是必要的,因为 8 位精度是有限的,并且在量化具有大值的向量时可能会导致严重的错误。 当这些错误通过多层传播时,它们也往往会放大。

由于将bitsandbytes 库集成到Hugging Face 生态系统中,我们可以轻松使用此技术。 我们只需要在加载模型时指定 load_in_8bit=True(它也需要GPU)。

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

model_int8 = AutoModelForCausalLM.from_pretrained(model_id,
                                             device_map='auto',
                                             load_in_8bit=True,
                                             )
print(f"Model size: {model_int8.get_memory_footprint():,} bytes")

输出结果如下:

Model size: 176,527,896 bytes

有了这行额外的代码,模型现在几乎小了三倍(168MB vs. 487MB)。 我们甚至可以像之前那样比较原始权重和量化权重的分布:

在本例中,我们看到 -2、-1、0、1、2 等附近的峰值。这些值对应于以 INT8 格式存储的参数(非异常值)。 你可以通过使用 model_int8.parameters() 打印模型的权重来验证它。

我们还可以使用这个量化模型生成文本并将其与原始模型进行比较。

# Generate text with quantized model
text_int8 = generate_text(model_int8, "I have a dream")

print(f"Original model:\n{original_text}")
print("-" * 50)
print(f"LLM.int8() model:\n{text_int8}")

输出结果如下:

Original model:
I have a dream, and it is a dream I believe I would get to live in my future. I love my mother, and there was that one time I had been told that my family wasn't even that strong. And then I got the
--------------------------------------------------
LLM.int8() model:
I have a dream. I don't know what will come of it, but I am going to have to look for something that will be right. I haven't thought about it for a long time, but I have to try to get that thing

再次,很难判断什么是最好的输出,但我们可以依靠困惑度度量来给我们一个(近似的)答案。

print(f"Perplexity (original):   {ppl.item():.2f}")

ppl = calculate_perplexity(model_int8, text_int8)
print(f"Perplexity (LLM.int8()): {ppl.item():.2f}")
Perplexity (original):   15.53
Perplexity (LLM.int8()): 7.93

在这种情况下,量化模型的困惑度是原始模型的两倍。 一般来说,情况并非如此,但它表明这种量化技术非常有竞争力。 事实上, LLM.int8() 的作者表明,性能下降非常低,可以忽略不计(<1%)。 然而,它在计算方面有额外的成本:对于大型模型,  LLM.int8() 大约慢 20% 左右。

4、结束语

本文概述了最流行的权重量化技术。 我们首先了解浮点表示,然后介绍两种 8 位量化技术:absmax 和零点量化。 然而,它们的局限性,特别是在处理异常值方面,导致了 LLM.int8(),这种技术也保留了模型的性能。 这种方法强调了权重量化领域所取得的进展,揭示了正确解决异常值的重要性。

展望未来,我们的下一篇文章将深入探讨 GPTQ 权重量化技术。 该技术由 Frantar 等人提出,仅使用 4 位,代表了权重量化领域的重大进步。 我们将提供有关如何使用 AutoGPTQ 库实现 GPTQ 的全面指南。


原文链接:LLM权重量化实战 - BimAnt

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

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

相关文章

庖丁解牛:NIO核心概念与机制详解

文章目录 Pre输入/输出Why NIO流与块的比较通道和缓冲区概述什么是缓冲区&#xff1f;缓冲区类型什么是通道&#xff1f;通道类型 NIO 中的读和写概述Demo : 从文件中读取1. 从FileInputStream中获取Channel2. 创建ByteBuffer缓冲区3. 将数据从Channle读取到Buffer中 Demo : 写…

基于静电放电算法优化概率神经网络PNN的分类预测 - 附代码

基于静电放电算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于静电放电算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于静电放电优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

JVM:字节码文件,类的生命周期,类加载器

JVM&#xff1a;字节码文件&#xff0c;类的生命周期&#xff0c;类加载器 为什么要学这门课程 1. 初识JVM1.1. 什么是JVM1.2. JVM的功能1.3. 常见的JVM 2. 字节码文件详解2.1. Java虚拟机的组成2.2. 字节码文件的组成2.2.1. 以正确的姿势打开文…

电脑软件:推荐一款非常实用的固态硬盘优化工具

目录 一、软件简介 二、工作原理 三、功能介绍 3.1、优化SSD设置 3.2、查看驱动器信息 3.3、查看SMART数据 3.4、停用Windows事件日志记录 3.5、禁用Windows碎片整理 3.6、时间戳停用 3.7、禁用引导文件的碎片整理 3.8、关闭短名称 四、使用教程 4.1 安装说明 4.…

OpenCV图像处理、计算机视觉实战应用

OpenCV图像处理、计算机视觉实战应用 专栏简介一、基于差异模型模板匹配缺陷检测二、基于NCC多角度多目标匹配三、基于zxing多二维码识别四、基于tesseract OCR字符识别 专栏简介 基于OpenCV C分享一些图像处理、计算机视觉实战项目。不定期持续更新&#xff0c;干货满满&…

[C/C++]数据结构 链表(单向链表,双向链表)

前言: 上一文中我们介绍了顺序表的特点及实现,但是顺序表由于每次扩容都是呈二倍增长(扩容大小是自己定义的),可能会造成空间的大量浪费,但是链表却可以解决这个问题. 概念及结构: 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接…

【自用总结】正项级数审敛法的总结

注&#xff1a;收敛半径的求法就是lim n->∞ |an1/an| ρ&#xff0c;而ρ1/R&#xff0c;最基本的不能忘。 比较判别法&#xff1a;从某项起&#xff0c;该级数后面的项均小于等于另一级数&#xff0c;则敛散性可进行一定的比较 可以看到&#xff0c;比较判别法实际上比较…

跟我一起来做一个音视频产品功能!

前言&#xff1a; 大家好&#xff0c;上来和大家汇报一下h264翻译进度&#xff0c;目前翻译完了第六章&#xff0c;第七章快翻译完了&#xff0c;马上可以翻译第八章。 在第七章翻译完了之后&#xff0c;我会做一个知识点总结出来&#xff0c;一起学习&#xff0c;一起进步&…

Android 13.0 Launcher3仿ios长按app图标实现抖动动画开始拖拽停止动画

1.概述 在13.0的系统rom定制化开发中,在对系统原生Launcher3的定制需求中,也有好多功能定制的,在ios等电子产品中 的一些好用的功能,也是可以被拿来借用的,所以在最近的产品开发需求中,需求要求模仿ios的 功能实现长按app图标实现抖动动画,接下来看如何分析该功能的实现…

【开源】基于JAVA的校园失物招领管理系统

项目编号&#xff1a; S 006 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S006&#xff0c;文末获取源码。} 项目编号&#xff1a;S006&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 招领管理模块2.2 寻物管理模块2.3 系…

主键问题以及分布式 id

分布式 id 需要处理的问题主要是同一时间在多台机器中保证生成的 id 唯一&#xff0c;为了这么做我们可以这么做&#xff1a; 分布式 id 生成策略 先说几个已经被淘汰的策略引出分布式 id 的问题 1&#xff0c;UUID&#xff1a;UUID 随机并且唯一&#xff0c;在单一的数据库…

调整COSWriter解决X-easypdf / PDFBOX生成大量数据时OOM问题

背景 业务需要生成一个15W数据左右的PDF交易报表。希望我们写在一个文件里&#xff0c;不拆分成多个PDF文件。 使用的技术组件 <dependency><groupId>wiki.xsx</groupId><artifactId>x-easypdf-pdfbox</artifactId><version>2.11.10<…

基于和声算法优化概率神经网络PNN的分类预测 - 附代码

基于和声算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于和声算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于和声优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

IPSecGRE

IPSec&GRE 手工方式建立IPSec隧道组网实验拓扑配置步骤第一步配置IP地址第二步配置静态路由第三步配置IPSec 抓包测试 GRE Over IPSec功能的配置组网实验拓扑配置命令 配置GRE使用静态路由组网图实验拓扑配置步骤1.配置RouterA2.配置RouterB3.配置RouterC4.验证配置结果 手…

【限时免费】20天拿下华为OD笔试之 【前缀和】2023B-最大子矩阵和【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录 题目描述与示例题目描述输入描述输出描述示例输入输出说明 解题思路如何表示一个子矩阵暴力解法二维前缀和优化二维前缀和矩阵的构建 代码解法一&#xff1a;二维前缀和PythonJavaC时空复杂度 解法二&#xff1a;暴力解法&#xff08;不推荐&#xff09;PythonJavaC时…

Pattern Recognition投稿经验

文章目录 ManuscriptTitle PageHighlightsAuthor BiographyDeclarationSubmit 合作推广&#xff0c;分享一个人工智能学习网站。计划系统性学习的同学可以了解下&#xff0c;点击助力博主脱贫( •̀ ω •́ )✧ 停更了大半年&#xff0c;近期终于完成了论文投稿&#xff0c;趁…

聚观早报 |联想集团Q2财季业绩;小鹏汽车Q3营收

【聚观365】11月17日消息 联想集团Q2财季业绩 小鹏汽车Q3营收 微软发布两款自研AI芯片 FAA批准SpaceX再次发射星际飞船 2023 OPPO开发者大会 联想集团Q2财季业绩 全球数字经济领导企业联想集团公布截至2023年9月30日的2023/24财年第二财季业绩&#xff1a;整体营收达到10…

闲聊从零开发一个2D数字人流程实战

.2D数字人技术 百度&#xff0c;腾讯&#xff0c;等大厂都有自己的数字平台制作&#xff08;套壳&#xff1a;api后台转发vue前端&#xff09;&#xff0c;国外也有出名的heygen&#xff08;非常厉害一个&#xff09;通过开源项目组合实现&#xff0c;再打通每个项目已api的形…

OpenAI 变天:Sam Altman 被踢出局,原 CTO 暂代临时 CEO

文章目录 灵魂人物 Sam Altman 离任 OpenAICEO 下台&#xff1a;OpenAI 也宫斗&#xff1f;个人简介 hello&#xff0c;大家好&#xff0c;我是 Lorin&#xff0c;一觉醒来科技圈发生了一件令人震惊的大事&#xff1a;Sam Altman 被踢出局&#xff0c;原 CTO 暂代临时 CEO。 灵…

Flask学习一:概述

搭建项目 安装框架 pip install Flask第一个程序 from flask import Flaskapp Flask(__name__)app.route(/) def hello_world():return "Hello World"if __name__ __main__:app.run()怎么说呢&#xff0c;感觉还不错的样子。 调试模式 if __name__ __main__:a…