当前位置: 首页 > news >正文

从零开始实现大语言模型(十六):加载开源大语言模型参数

1. 前言

预训练大语言模型的难点不在于算法,而在于数据和算力,绝大多数企业和机构都没有预训练大语言模型的算力资源。在工业界的大语言模型应用实践中,通常会使用领域数据微调开源大语言模型参数,以构建领域大语言模型。

本文介绍加载开源大语言模型参数以替代大语言模型GPTModel中的随机初始化参数的方法。后续微调大语言模型部分内容将分别使用监督微调及指令微调方法,微调大语言模型GPTModel参数,使大语言模型具备文本分类及回答问题能力。

2. 获取开源大语言模型参数

OpenAI开源了其使用TensorFlow框架训练出来的大语言模型GPT-2的参数。可以使用如下代码,访问OpenAI官方提供的模型参数下载地址,下载开源大语言模型GPT-2 small版本(124M)的参数:

import os
import urllib.request
from tqdm import tqdmdef download_openai_params(model_size, openai_params_dir):allowed_sizes = ["124M", "355M", "774M", "1558M"]if model_size not in allowed_sizes:raise ValueError(f"model_size not in {allowed_sizes}")params_dir = os.path.join(openai_params_dir, "gpt2_" + model_size)os.makedirs(params_dir, exist_ok=True)base_url = "https://openaipublic.blob.core.windows.net/gpt-2/models"filenames = ["checkpoint", "encoder.json", "hparams.json", "vocab.bpe","model.ckpt.index", "model.ckpt.meta", "model.ckpt.data-00000-of-00001"]for filename in filenames:file_url = os.path.join(base_url, model_size, filename)file_path = os.path.join(params_dir, filename)with urllib.request.urlopen(file_url) as response:file_size = int(response.headers.get("Content-Length", 0))if os.path.exists(file_path):file_size_local = os.path.getsize(file_path)if file_size == file_size_local:print(f"File already exists and is up-to-date: {file_path}")continueblock_size = 1024progress_bar_description = os.path.basename(file_url)with tqdm(total=file_size, unit="iB", unit_scale=True, desc=progress_bar_description) as progress_bar:with open(file_path, "wb") as file:while True:chunk = response.read(block_size)if not chunk:breakfile.write(chunk)progress_bar.update(len(chunk))download_openai_params(model_size="124M", openai_params_dir="openai_params")

执行上面代码,打印结果如下:

checkpoint: 100%|██████████████████████████████████████████████████████████████████| 77.0/77.0 [00:00<00:00, 73.2kiB/s]
encoder.json: 100%|███████████████████████████████████████████████████████████████| 1.04M/1.04M [00:04<00:00, 245kiB/s]
hparams.json: 100%|████████████████████████████████████████████████████████████████████████| 90.0/90.0 [00:00<?, ?iB/s]
vocab.bpe: 100%|████████████████████████████████████████████████████████████████████| 456k/456k [00:00<00:00, 489kiB/s]
model.ckpt.index: 100%|██████████████████████████████████████████████████████████| 5.21k/5.21k [00:00<00:00, 1.73MiB/s]
model.ckpt.meta: 100%|██████████████████████████████████████████████████████████████| 471k/471k [00:00<00:00, 505kiB/s]
model.ckpt.data-00000-of-00001: 100%|███████████████████████████████████████████████| 498M/498M [13:19<00:00, 622kiB/s]

OpenAI开源的大语言模型GPT-2的训练框架是TensorFlow,可以使用tf.train.latest_checkpoint函数获取模型的checkpoint路径,并使用tf.train.list_variables函数打印模型参数信息,具体代码如下所示:

import tensorflow as tfckpt_path = tf.train.latest_checkpoint("openai_params/gpt2_124M")
variables = tf.train.list_variables(ckpt_path)
variables

执行上面代码,打印结果如下:

[('model/h0/attn/c_attn/b', [2304]),('model/h0/attn/c_attn/w', [1, 768, 2304]),('model/h0/attn/c_proj/b', [768]),('model/h0/attn/c_proj/w', [1, 768, 768]),('model/h0/ln_1/b', [768]),('model/h0/ln_1/g', [768]),('model/h0/ln_2/b', [768]),('model/h0/ln_2/g', [768]),('model/h0/mlp/c_fc/b', [3072]),('model/h0/mlp/c_fc/w', [1, 768, 3072]),('model/h0/mlp/c_proj/b', [768]),('model/h0/mlp/c_proj/w', [1, 3072, 768]),[...]('model/h9/attn/c_attn/b', [2304]),('model/h9/attn/c_attn/w', [1, 768, 2304]),('model/h9/attn/c_proj/b', [768]),('model/h9/attn/c_proj/w', [1, 768, 768]),('model/h9/ln_1/b', [768]),('model/h9/ln_1/g', [768]),('model/h9/ln_2/b', [768]),('model/h9/ln_2/g', [768]),('model/h9/mlp/c_fc/b', [3072]),('model/h9/mlp/c_fc/w', [1, 768, 3072]),('model/h9/mlp/c_proj/b', [768]),('model/h9/mlp/c_proj/w', [1, 3072, 768]),('model/ln_f/b', [768]),('model/ln_f/g', [768]),('model/wpe', [1024, 768]),('model/wte', [50257, 768])]

3. 加载开源大语言模型参数

使用梯度下降算法训练深度神经网络,会先随机初始化深度神经网络模型参数,并使用梯度下降算法逐步更新深度神经网络参数直至收敛。在工业界的大语言模型应用实践中,通常会使用开源大语言模型参数替代大语言模型中的随机初始化参数,以解决预训练大语言模型的算力资源缺乏问题。

如下面的代码所示,加载OpenAI的开源大语言模型GPT-2的参数以替代大语言模型GPTModel中的随机初始化参数,首先需要使用如下代码读取开源大语言模型参数,并构造参数字典params。参数字典params的key为OpenAI开源的大语言模型GPT-2中各个子模块参数的名称,value为各个子模块参数对应的torch.nn.Parameter。具体代码如下所示:

import json
import torch
import numpy as npdef load_openai_ckpt(ckpt_dir):ckpt_path = tf.train.latest_checkpoint(ckpt_dir)with open(os.path.join(ckpt_dir, "hparams.json"), "rt", encoding="utf-8") as f:settings = json.load(f)params = {"blocks": [{} for _ in range(settings["n_layer"])]}for name, _ in tf.train.list_variables(ckpt_path):variable_array = np.squeeze(tf.train.load_variable(ckpt_path, name))variable_array = torch.nn.Parameter(torch.tensor(variable_array))variable_name_parts = name.split("/")[1:]target_dict = paramsif variable_name_parts[0].startswith("h"):layer_number = int(variable_name_parts[0][1:])target_dict = params["blocks"][layer_number]for key in variable_name_parts[1:-1]:target_dict = target_dict.setdefault(key, {})last_key = variable_name_parts[-1]target_dict[last_key] = variable_array  # noqareturn paramsparams = load_openai_ckpt("openai_params/gpt2_124M")print("Parameter dictionary keys:", params.keys())
print("Token embedding parameter dimensions:", params["wte"].shape)
print("Token embedding parameter:\n", params["wte"])

执行上面代码,打印结果如下:

Parameter dictionary keys: dict_keys(['blocks', 'b', 'g', 'wpe', 'wte'])
Token embedding parameter dimensions: torch.Size([50257, 768])
Token embedding parameter:Parameter containing:
tensor([[-0.1101, -0.0393,  0.0331,  ..., -0.1364,  0.0151,  0.0453],[ 0.0403, -0.0486,  0.0462,  ...,  0.0861,  0.0025,  0.0432],[-0.1275,  0.0479,  0.1841,  ...,  0.0899, -0.1297, -0.0879],...,[-0.0445, -0.0548,  0.0123,  ...,  0.1044,  0.0978, -0.0695],[ 0.1860,  0.0167,  0.0461,  ..., -0.0963,  0.0785, -0.0225],[ 0.0514, -0.0277,  0.0499,  ...,  0.0070,  0.1552,  0.1207]],requires_grad=True)

定义函数load_openai_params,并按照如下规则使用参数字典params中的参数替换大语言模型GPTModel中的相应参数:

  • 使用wte参数替代Token Embedding层参数gpt2_small.tok_emb.weight

  • 使用wpe参数替代Positional Embedding层参数gpt2_small.pos_emb.weight

  • 使用attn.c_attn.w参数替代多头注意力子模块中的att.W_qkv.weight

  • 使用attn.c_attn.b参数替代多头注意力子模块中的att.W_qkv.bias

  • 使用attn.c_proj.w参数替代多头注意力子模块中的att.out_proj.weight

  • 使用attn.c_proj.b参数替代多头注意力子模块中的att.out_proj.bias

  • 使用mlp.c_fc.w参数替代前馈神经网络子模块中第一个Linear层的ff.layers[0].weight

  • 使用mlp.c_fc.b参数替代前馈神经网络子模块中第一个Linear层的ff.layers[0].bias

  • 使用mlp.c_proj.w参数替代前馈神经网子络模块中第二个Linear层的ff.layers[2].weight

  • 使用mlp.c_proj.b参数替代前馈神经网子络模块中第二个Linear层的ff.layers[2].bias

  • 使用ln_1.g参数替代多头注意力子模块中Layer Normalization层参数norm1.scale

  • 使用ln_1.b参数替代多头注意力子模块中Layer Normalization层参数norm1.shift

  • 使用ln_2.g参数替代前馈神经网络子模块中Layer Normalization层参数norm2.scale

  • 使用ln_2.b参数替代前馈神经网络子模块中Layer Normalization层参数norm2.shift

  • 使用g参数替代对最后的输出层的输入张量做变换的Layer Normalization层参数final_norm.scale

  • 使用b参数替代对最后的输出层的输入张量做变换的Layer Normalization层参数final_norm.shift

  • 使用wte参数替代最后的输出层参数out_linear.weight

具体代码如下所示:

def load_openai_params(model, params):model.tok_emb.weight = params['wte']model.pos_emb.weight = params['wpe']for b in range(len(params["blocks"])):model.trf_blocks[b].att.W_qkv.weight = torch.nn.Parameter(params["blocks"][b]["attn"]["c_attn"]["w"].T)model.trf_blocks[b].att.W_qkv.bias = params["blocks"][b]["attn"]["c_attn"]["b"]model.trf_blocks[b].att.out_proj.weight = torch.nn.Parameter(params["blocks"][b]["attn"]["c_proj"]["w"].T)model.trf_blocks[b].att.out_proj.bias = params["blocks"][b]["attn"]["c_proj"]["b"]model.trf_blocks[b].ff.layers[0].weight = torch.nn.Parameter(params["blocks"][b]["mlp"]["c_fc"]["w"].T)model.trf_blocks[b].ff.layers[0].bias = params["blocks"][b]["mlp"]["c_fc"]["b"]model.trf_blocks[b].ff.layers[2].weight = torch.nn.Parameter(params["blocks"][b]["mlp"]["c_proj"]["w"].T)model.trf_blocks[b].ff.layers[2].bias = params["blocks"][b]["mlp"]["c_proj"]["b"]model.trf_blocks[b].norm1.scale = params["blocks"][b]["ln_1"]["g"]model.trf_blocks[b].norm1.shift = params["blocks"][b]["ln_1"]["b"]model.trf_blocks[b].norm2.scale = params["blocks"][b]["ln_2"]["g"]model.trf_blocks[b].norm2.shift = params["blocks"][b]["ln_2"]["b"]model.final_norm.scale = params["g"]model.final_norm.shift = params["b"]model.out_linear.weight = params["wte"]

实例化大语言模型gpt2_small,使用函数load_openai_params加载OpenAI的开源大语言模型GPT-2的参数,并调用从零开始实现大语言模型(十二):文本生成策略所述文本生成函数generate_text,打印生成的文本信息:

import tiktoken
# from [从零开始实现大语言模型(七):多头注意力机制] import MultiHeadAttention
# from [从零开始实现大语言模型(八):Layer Normalization] import LayerNorm
# from [从零开始实现大语言模型(九):前馈神经网络与GELU激活函数] import GELU, FeedForward
# from [从零开始实现大语言模型(十一):构建大语言模型GPTModel] import TransformerBlock, GPTModel
# from [从零开始实现大语言模型(十二):文本生成策略] import generate_textembedding_dim = 768
num_layers = 12
num_heads = 12
context_len = 1024
vocabulary_size = 50257
dropout = 0.1
qkv_bias = Truetokenizer = tiktoken.encoding_for_model("gpt2")
gpt2_small = GPTModel(embedding_dim=embedding_dim,num_layers=num_layers,num_heads=num_heads,context_len=context_len,vocabulary_size=vocabulary_size,dropout=dropout,qkv_bias=qkv_bias
)load_openai_params(gpt2_small, params)torch.manual_seed(123)
text = generate_text(model=gpt2_small, start_context="Every effort moves you", max_new_tokens=23, context_size=1024, tokenizer=tokenizer, temperature=0.3, top_k=50, compact_format=True
)
print(text)

执行上面代码,打印结果如下:

Every effort moves you forward, but it's a process. It's a process of learning, and it's a process of learning.

4. Hugging Face与Model Scope

Hugging Face与Model Scope是全球最大的两个开源模型社区,可以直接通过Hugging Face或Model Scope加载开源大语言模型参数。如下面的代码所示,可以直接使用GPT2Model.from_pretrained函数,从Hugging Face中加载开源大语言模型GPT-2:

from transformers import GPT2Modelhf_gpt2_small = GPT2Model.from_pretrained("openai-community/gpt2", cache_dir="huggingface_params")
print(hf_gpt2_small)

执行上面代码,打印结果如下:

GPT2Model((wte): Embedding(50257, 768)(wpe): Embedding(1024, 768)(drop): Dropout(p=0.1, inplace=False)(h): ModuleList((0): GPT2Block((ln_1): LayerNorm((768,), eps=1e-05, elementwise_affine=True)(attn): GPT2Attention((c_attn): Conv1D()(c_proj): Conv1D()(attn_dropout): Dropout(p=0.1, inplace=False)(resid_dropout): Dropout(p=0.1, inplace=False))(ln_2): LayerNorm((768,), eps=1e-05, elementwise_affine=True)(mlp): GPT2MLP((c_fc): Conv1D()(c_proj): Conv1D()(act): NewGELUActivation()(dropout): Dropout(p=0.1, inplace=False)))[...](11): GPT2Block((ln_1): LayerNorm((768,), eps=1e-05, elementwise_affine=True)(attn): GPT2Attention((c_attn): Conv1D()(c_proj): Conv1D()(attn_dropout): Dropout(p=0.1, inplace=False)(resid_dropout): Dropout(p=0.1, inplace=False))(ln_2): LayerNorm((768,), eps=1e-05, elementwise_affine=True)(mlp): GPT2MLP((c_fc): Conv1D()(c_proj): Conv1D()(act): NewGELUActivation()(dropout): Dropout(p=0.1, inplace=False))))(ln_f): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
)

定义继承自torch.nn.ModuleHFGPT2ModelWrapper类,在其__init__方法中创建大语言模型GPT-2的输出层self.out_linear,并使用Token Embedding层参数替代输出层self.out_linear的随机初始化参数。在forward方法中,将x输入从Hugging Face中加载的大语言模型hf_gpt2_small,并将大语言模型hf_gpt2_small输出的last_hidden_state输入在__init__方法中创建的输出层self.out_linear。创建HFGPT2ModelWrapper类对象gpt2_small,并调用文本生成函数generate_text,打印生成的文本信息:

class HFGPT2ModelWrapper(torch.nn.Module):def __init__(self, hf_model):super().__init__()self.hf_model = hf_modelself.out_linear = torch.nn.Linear(hf_model.wte.weight.shape[1], hf_model.wte.weight.shape[0], bias=False)self.out_linear.weight = hf_model.wte.weightdef forward(self, x):last_hidden_state = self.hf_model(x)["last_hidden_state"]return self.out_linear(last_hidden_state)gpt2_small = HFGPT2ModelWrapper(hf_gpt2_small)torch.manual_seed(123)
text = generate_text(model=gpt2_small, start_context="Every effort moves you", max_new_tokens=23, context_size=1024, tokenizer=tokenizer, temperature=0.3, top_k=50, compact_format=True
)
print(text)

执行上面代码,打印结果如下:

Every effort moves you forward, but it's a process. It's a process of learning, and it's a process of learning.

可以进一步定义函数load_huggingface_params,使用从Hugging Face中加载的开源大语言模型GPT-2参数替代大语言模型GPTModel中的随机初始化参数:

def load_huggingface_params(model, hf_model):state_dict = hf_model.state_dict()model.pos_emb.weight = torch.nn.Parameter(state_dict["wpe.weight"])model.tok_emb.weight = torch.nn.Parameter(state_dict["wte.weight"])for b in range(len(hf_model.h)):model.trf_blocks[b].att.W_qkv.weight = torch.nn.Parameter(state_dict[f"h.{b}.attn.c_attn.weight"].T)model.trf_blocks[b].att.W_qkv.bias = torch.nn.Parameter(state_dict[f"h.{b}.attn.c_attn.bias"])model.trf_blocks[b].att.out_proj.weight = torch.nn.Parameter(state_dict[f"h.{b}.attn.c_proj.weight"].T)model.trf_blocks[b].att.out_proj.bias = torch.nn.Parameter(state_dict[f"h.{b}.attn.c_proj.bias"])model.trf_blocks[b].ff.layers[0].weight = torch.nn.Parameter(state_dict[f"h.{b}.mlp.c_fc.weight"].T)model.trf_blocks[b].ff.layers[0].bias = torch.nn.Parameter(state_dict[f"h.{b}.mlp.c_fc.bias"])model.trf_blocks[b].ff.layers[2].weight = torch.nn.Parameter(state_dict[f"h.{b}.mlp.c_proj.weight"].T)model.trf_blocks[b].ff.layers[2].bias = torch.nn.Parameter(state_dict[f"h.{b}.mlp.c_proj.bias"])model.trf_blocks[b].norm1.scale = torch.nn.Parameter(state_dict[f"h.{b}.ln_1.weight"])model.trf_blocks[b].norm1.shift = torch.nn.Parameter(state_dict[f"h.{b}.ln_1.bias"])model.trf_blocks[b].norm2.scale = torch.nn.Parameter(state_dict[f"h.{b}.ln_2.weight"])model.trf_blocks[b].norm2.shift = torch.nn.Parameter(state_dict[f"h.{b}.ln_2.bias"])model.final_norm.scale = torch.nn.Parameter(state_dict[f"ln_f.weight"])model.final_norm.shift = torch.nn.Parameter(state_dict[f"ln_f.bias"])model.out_linear.weight = torch.nn.Parameter(state_dict["wte.weight"])

实例化大语言模型gpt2_small,使用函数load_huggingface_params加载Hugging Face中开源的大语言模型GPT-2的参数,并调用文本生成函数generate_text,打印生成的文本信息:

embedding_dim = 768
num_layers = 12
num_heads = 12
context_len = 1024
vocabulary_size = 50257
dropout = 0.1
qkv_bias = Truegpt2_small = GPTModel(embedding_dim=embedding_dim,num_layers=num_layers,num_heads=num_heads,context_len=context_len,vocabulary_size=vocabulary_size,dropout=dropout,qkv_bias=qkv_bias
)load_huggingface_params(gpt2_small, hf_gpt2_small)torch.manual_seed(123)
text = generate_text(model=gpt2_small, start_context="Every effort moves you", max_new_tokens=23, context_size=1024, tokenizer=tokenizer, temperature=0.3, top_k=50, compact_format=True
)
print(text)

执行上面代码,打印结果如下:

Every effort moves you forward, but it's a process. It's a process of learning, and it's a process of learning.

5. 结束语

未完待续……

相关文章:

从零开始实现大语言模型(十六):加载开源大语言模型参数

1. 前言 预训练大语言模型的难点不在于算法&#xff0c;而在于数据和算力&#xff0c;绝大多数企业和机构都没有预训练大语言模型的算力资源。在工业界的大语言模型应用实践中&#xff0c;通常会使用领域数据微调开源大语言模型参数&#xff0c;以构建领域大语言模型。 本文介…...

Spark,数据提取和保存

以下是使用 Spark 进行数据提取&#xff08;读取&#xff09;和保存&#xff08;写入&#xff09;的常见场景及代码示例&#xff08;基于 Scala/Java/Python&#xff0c;不含图片操作&#xff09;&#xff1a; 一、数据提取&#xff08;读取&#xff09; 1. 读取文件数据&a…...

java19

1.集合体系结构 注意&#xff1a; 2.collection遍历之迭代器遍历 一次循环只能一次next方法的原因&#xff1a; 原因&#xff1a;集合长度是单数就报错 3.collection遍历之增强for遍历 如何代码简写呢&#xff1a;集合名.for回车 4.collection遍历之Lambda表达式遍历 5.使用多态…...

从0到1吃透卷积神经网络(CNN):原理与实战全解析

一、开篇&#xff1a;CNN 在 AI 领域的地位 在当今人工智能&#xff08;AI&#xff09;飞速发展的时代&#xff0c;卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;简称 CNN&#xff09;无疑是深度学习领域中最为耀眼的明星之一 。它就像是 AI 世界里的超级…...

建一个结合双向长短期记忆网络(BiLSTM)和条件随机场(CRF)的模型

构建一个结合双向长短期记忆网络&#xff08;BiLSTM&#xff09;和条件随机场&#xff08;CRF&#xff09;的模型&#xff0c;通常用于序列标注任务&#xff0c;如命名实体识别&#xff08;NER&#xff09;、词性标注&#xff08;POS Tagging&#xff09;等。下面我将通过口述的…...

mvc-ioc实现

IOC 1&#xff09;耦合/依赖 依赖&#xff0c;是谁离不开谁 就比如上诉的Controller层必须依赖于Service层&#xff0c;Service层依赖于Dao 在软件系统中&#xff0c;层与层之间存在依赖。我们称之为耦合 我们系统架构或者设计的一个原则是&#xff…...

符合Python风格的对象(再谈向量类)

再谈向量类 为了说明用于生成对象表示形式的众多方法&#xff0c;我们将使用一个 Vector2d 类&#xff0c;它与第 1 章中的类似。这一节和接下来的几节会不断实 现这个类。我们期望 Vector2d 实例具有的基本行为如示例 9-1 所示。 示例 9-1 Vector2d 实例有多种表示形式 &g…...

4.1.8文件共享

知识总览 基于索引节点的共享方式(硬链接)&#xff1a; 让不同用户的文件目录项指向同一个文件的索引节点 用户1创建文件1&#xff0c;并让文件目录项aaa指向了文件1&#xff0c;这个文件对应了一个索引节点&#xff0c;这个索引节点 包含了文件的物理地址和文件的其他属性信…...

[LevelDB]LevelDB版本管理的黑魔法-为什么能在不锁表的情况下管理数据?

文章摘要 LevelDB的日志管理系统是怎么通过双链表来进行数据管理为什么LevelDB能够在不锁表的情况下进行日志新增 适用人群: 对版本管理机制有开发诉求&#xff0c;并且希望参考LevelDB的版本开发机制。数据库相关从业者的专业人士。计算机狂热爱好者&#xff0c;对计算机的…...

普通用户的服务器连接与模型部署相关记录

普通用户的服务器连接与模型部署相关记录 一、从登录到使用自己的conda 1.账号登陆&#xff1a; ssh xxx172.31.226.236 2.下载与安装conda&#xff1a; 下载conda&#xff1a; wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh 安装con…...

WebSocket解决方案的一些细节阐述

今天我们来看看WebSocket解决方案的一些细节问题&#xff1a; 实际上&#xff0c;集成WebSocket的方法都有相关的工程挑战&#xff0c;这可能会影响项目成本和交付期限。在最简单的层面上&#xff0c;构建 WebSocket 解决方案似乎是添加接收实时更新功能的前进方向。但是&…...

架构思维:构建高并发扣减服务_分布式无主架构

文章目录 Pre无主架构的任务简单实现分布式无主架构 设计和实现扣减中的返还什么是扣减的返还返还实现原则原则一&#xff1a;扣减完成才能返还原则二&#xff1a;一次扣减可以多次返还原则三&#xff1a;返还的总数量要小于等于原始扣减的数量原则四&#xff1a;返还要保证幂等…...

C++函数基础:定义与调用函数,参数传递(值传递、引用传递)详解

1. 引言 函数是C编程中的核心概念之一&#xff0c;它允许我们将代码模块化&#xff0c;提高代码的可读性、复用性和可维护性。本文将深入探讨&#xff1a; 函数的定义与调用参数传递方式&#xff08;值传递 vs 引用传递&#xff09;应用场景与最佳实践 2. 函数的定义与调用 …...

深入解析Python中的Vector2d类:从基础实现到特殊方法的应用

引言 在Python面向对象编程中&#xff0c;特殊方法&#xff08;或称魔术方法&#xff09;是实现对象丰富行为的关键。本文将以Vector2d类为例&#xff0c;详细讲解如何通过特殊方法为自定义类添加多种表示形式和操作能力。 Vector2d类的基本行为 Vector2d类是一个二维向量类…...

【25软考网工】第六章(7)网络安全防护系统

博客主页&#xff1a;christine-rr-CSDN博客 ​​专栏主页&#xff1a;软考中级网络工程师笔记 ​​​ 大家好&#xff0c;我是christine-rr !目前《软考中级网络工程师》专栏已经更新三十多篇文章了&#xff0c;每篇笔记都包含详细的知识点&#xff0c;希望能帮助到你&#x…...

Mac下载bilibili视频

安装 安装 yt-dlp brew install yt-dlp安装FFmpeg 用于合并音视频流、转码等操作 brew install ffmpeg使用 下载单个视频 查看可用格式 yt-dlp -F --cookies-from-browser chrome "https://www.bilibili.com/video/BV15B4y1G7F3?spm_id_from333.788.recommend_more_vid…...

6个月Python学习计划:从入门到AI实战(前端开发者进阶指南)

作者&#xff1a;一名前端开发者的进阶日志 计划时长&#xff1a;6个月 每日学习时间&#xff1a;2小时 覆盖方向&#xff1a;Python基础、爬虫开发、数据分析、后端开发、人工智能、深度学习 &#x1f4cc; 目录 学习目标总览每日时间分配建议第1月&#xff1a;Python基础与编…...

批量处理 Office 文档 高画质提取图片、视频、音频素材助手

各位办公小能手们&#xff01;你们有没有遇到过想从 Office 文档里提取图片、音频和视频&#xff0c;却又搞得焦头烂额的情况&#xff1f;今天就给大家介绍一款超厉害的工具——OfficeImagesExtractor&#xff01; 这货的核心功能那可真是杠杠的&#xff01;首先是高画质提取&a…...

【甲方安全建设】Python 项目静态扫描工具 Bandit 安装使用详细教程

文章目录 一、工具简介二、工具特点1.聚焦安全漏洞检测2.灵活的扫描配置3.多场景适配4.轻量且社区活跃三、安装步骤四、使用方法场景1:扫描单个Python文件场景2:递归扫描整个项目目录五、结果解读六、总结一、工具简介 Bandit 是由Python官方推荐的静态代码分析工具(SAST)…...

【推荐】新准则下对照会计报表172个会计科目解释

序号 科目名称 对应的会计报表项目 序号 科目名称 对应的会计报表项目   一、资产类     二、负债类   1 1001 库存现金 货币资金 103 2001 短期借款 短期借款 2 1002 银行存款 货币资金 104 2101 交易性金融负债 易性金融负债 3 1012 其他货币资…...

IntelliJ IDEA设置编码集

在IntelliJ IDEA中设置Properties文件的编码格式&#xff0c;主要涉及以下步骤和注意事项&#xff1a; 1. ‌全局和项目编码设置‌ 打开设置界面&#xff1a;File -> Settings -> Editor -> File Encodings。在Global Encoding和Project Encoding下拉菜单中均选择UT…...

类魔方 :多变组合,灵活复用

文章目录 一、类的基础1. 类的基本结构与语法1. 类的定义与实例化2. 成员变量&#xff08;属性&#xff09;3. 构造函数&#xff08;Constructor&#xff09;4. 成员方法 2. 访问修饰符1. 基本访问规则2. 子类对父类方法的重写3. 构造函数的访问修饰符4. 参数属性与继承总结 3.…...

支持多方式拼接图片的软件

软件介绍 本文介绍一款名为 PicMerger 的图片拼接软件。 拼接亮点 PicMerger 这款软件最大的亮点在于&#xff0c;它能够将不同分辨率的图片完美地拼接在一起。拼接时会自动以分辨率最小的图片为标准&#xff0c;操作十分方便。 拼接方式与设置 该软件支持横向和纵向的拼接…...

Qt音视频开发过程中一个疑难杂症的解决方法/ffmpeg中采集本地音频设备无法触发超时回调

一、前言 最近在做实时音视频通话的项目中&#xff0c;遇到一个神奇的问题&#xff0c;那就是用ffmpeg采集本地音频设备&#xff0c;当音频设备拔掉后&#xff0c;采集过程会卡死在av_read_frame函数中&#xff0c;尽管设置了超时时间&#xff0c;也设置了超时回调interrupt_c…...

Android studio Could not move temporary workspace

Android studio Could not move temporary workspace 在Window上运行AS出现Could not move temporary workspace报错方法一&#xff08;有效&#xff09;方法二方法三方法四总结 在Window上运行AS出现Could not move temporary workspace报错 Could not move temporary workspa…...

深度估计中为什么需要已知相机基线(known camera baseline)?

在计算机视觉和立体视觉的上下文中&#xff0c;“已知相机基线”&#xff08;known camera baseline&#xff09;的解释 1. 相机基线的定义 相机基线是指两个相机中心之间的距离。在立体视觉系统中&#xff0c;通常有两个相机&#xff08;或一个相机在不同位置拍摄两张图像&a…...

Spring Cloud 技术实战

Spring Cloud 简介 Spring Cloud 是基于 Spring Boot 构建的微服务框架&#xff0c;提供了一套完整的微服务解决方案。它利用 Spring Boot 的开发便利性&#xff0c;并通过各种组件简化分布式系统的开发。 核心组件 Spring Cloud Netflix Eureka: 服务注册与发现Spring Clou…...

《云端共生体:Flutter与AR Cloud如何改写社交交互规则》

当Flutter遇上AR Cloud&#xff0c;一场关于社交应用跨设备增强现实内容共享与协作的变革正在悄然发生。 Flutter是谷歌推出的一款开源UI软件开发工具包&#xff0c;其最大的优势在于能够实现一套代码&#xff0c;多平台部署&#xff0c;涵盖iOS、Android、Web、Windows、macO…...

【数据结构】1-3 算法的时间复杂度

数据结构知识点合集&#xff1a;数据结构与算法 • 知识点 • 时间复杂度的定义 1、算法时间复杂度 事前预估算法时间开销T(n)与问题规模 n 的关系&#xff08;T 表示 “time”&#xff09; 2、语句频度 算法中语句的执行次数 对于以上算法&#xff0c;语句频度&#xff1a;…...

Science Robotics 封面论文:基于形态学开放式参数化的仿人灵巧手设计用于具身操作

人形机械手具有无与伦比的多功能性和精细运动技能&#xff0c;使其能够精确、有力和稳健地执行各种任务。在古生物学记录和动物王国中&#xff0c;我们看到了各种各样的替代手和驱动设计。了解形态学设计空间和由此产生的涌现行为不仅可以帮助我们理解灵巧的作用及其演变&#…...

Vue百日学习计划Day24-28天详细计划-Gemini版

总目标: 在 Day 24-27 熟练掌握 Vue.js 的各种模板语法&#xff0c;包括文本插值、属性绑定、条件渲染、列表渲染、事件处理和表单绑定&#xff0c;并能结合使用修饰符。 所需资源: Vue 3 官方文档 (模板语法): https://cn.vuejs.org/guide/essentials/template-syntax.htmlVu…...

C++_数据结构_哈希表(hash)实现

✨✨ 欢迎大家来到小伞的大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 小伞的主页&#xff1a;xiaosan_blog 制作不易&#xff01;点个赞吧&#xff01;&#xff01;谢谢喵&#xff01;&…...

elasticsearch kibana ik 各版本下载

https://release.infinilabs.com/analysis-ik/stable/或者 https://github.com/infinilabs/analysis-ik/releases...

Uniapp 与 Uniapp X 对比:新手上手指南及迁移到 Uniapp X 的注意事项

文章目录 前言一、Uniapp 与 Uniapp X 核心区别二、Uniapp X 的核心优势三、新手学习 Uniapp X 必备技能栈3.1 基础技能要求3.2 平台相关知识3.3 工具链掌握 四、从 Uniapp 迁移到 Uniapp X 的注意事项4.1 语法转换&#xff1a;4.2 组件替换&#xff1a;4.3 状态管理&#xff1…...

SQL性能分析

查看数据库操作频次 使用SHOW GLOBAL STATUS LIKE Com_______; 指令&#xff0c;能查看当前数据库的INSERT、UPDATE、DELETE、SELECT访问频次 。若以查询为主&#xff0c;需重点优化查询相关性能&#xff0c;如索引&#xff1b;若以增删改为主&#xff0c;可考虑事务处理、批量…...

CANoe测试应用案例之A2L

写在前面 本系列文章主要讲解CANoe测试应用案例之A2L的相关知识&#xff0c;希望能帮助更多的同学认识和了解CANoe测试。 若有相关问题&#xff0c;欢迎评论沟通&#xff0c;共同进步。(*^▽^*) CANoe Option AMD/XCP支持加载A2L到CANoe中&#xff0c;方便ECU内部变量在功能验…...

H2数据库源码学习+debug, 数据库 sql、数据库引擎、数据库存储从此不再神秘

一、源码结构概览 H2源码采用标准Maven结构&#xff0c;核心模块在src/main/org/h2目录下&#xff1a; ├── command/ # SQL解析与执行 ├── engine/ # 数据库引擎核心&#xff08;会话、事务&#xff09; ├── table/ # 表结构定义与操作 ├── index/ # 索引实现&am…...

PopSQL:一个支持团队协作的SQL开发工具

PopSQL 是一款专为团队协作设计的现代化 SQL 编辑器&#xff0c;通过通团队过协作编写 SQL 查询、交互式可视化以及共享结果提升数据分析和管理效率。 PopSQL 提供了基于 Web 的在线平台以及跨系统&#xff08;Windows、macOS、Linux&#xff09;的桌面应用&#xff0c;包括免费…...

tomcat查看状态页及调优信息

准备工作 先准备一台已经安装好tomcat的虚拟机&#xff0c;tomcat默认是状态页是默认被禁用的 1.添加授权用户 vim /usr/local/tomcat/conf/tomcat-users.xml22 <role rolename"manager-gui"/>23 <user username"admin" password"tomcat&q…...

贝塞尔曲线原理

文章目录 一、 低阶贝塞尔曲线1.一阶贝塞尔曲线2. 二阶贝塞尔曲线3. 三阶贝塞尔曲线 一、 低阶贝塞尔曲线 1.一阶贝塞尔曲线 如下图所示&#xff0c; P 0 ​ P_0​ P0​​, P 1 ​ P_1​ P1​​ 是平面中的两点&#xff0c;则 B ( t ) B ( t ) B(t) 代表平面中的一段线段。…...

【MYSQL】笔记

&#x1f4da; 博主的专栏 &#x1f427; Linux | &#x1f5a5;️ C | &#x1f4ca; 数据结构 | &#x1f4a1;C 算法 | &#x1f152; C 语言 | &#x1f310; 计算机网络 在ubuntu中&#xff0c;改配置文件&#xff1a; sudo nano /etc/mysql/mysql.conf.d/mysq…...

构建 TypoView:一个富文本样式预览工具的全流程记录

我正在参加CodeBuddy「首席试玩官」内容创作大赛&#xff0c;本文所使用的 CodeBuddy 免费下载链接&#xff1a;腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 在一次和 CodeBuddy 的日常交流中&#xff0c;我提出了一个构想&#xff1a;能不能帮我从零构建一个富文本样式…...

使用conda创建python虚拟环境,并自定义路径

创建虚拟环境 conda create --prefixE:/ai-tools/Luoxuejiao/envs/Luo24 python3.8 此时虚拟环境没有名字&#xff0c;只有路径&#xff0c;下面将名字添加到配置中&#xff1a; conda config --append envs_dirs E:/ai-tools/Luoxuejiao/envs/...

【自然语言处理与大模型】向量数据库技术

向量数据库&#xff0c;是专门为向量检索设计的中间件&#xff01; 高效存储、快速检索和管理高纬度向量数据的系统称为向量数据库 一、向量数据库是什么有什么用&#xff1f; 向量数据库是一种专门用于高效存储和检索高维向量数据的系统。它通过嵌入模型将各类非结构化数据&am…...

Java中的伪共享(False Sharing):隐藏的性能杀手与高并发优化实战

引言 在高性能Java应用中&#xff0c;开发者通常会关注锁竞争、GC频率等显性问题&#xff0c;但一个更隐蔽的陷阱——伪共享&#xff08;False Sharing&#xff09;​——却可能让精心设计的并发代码性能骤降50%以上。伪共享是由CPU缓存架构引发的底层问题&#xff0c;常见于多…...

【数据结构】2-3-3单链表的查找

数据结构知识点合集 知识点 单链表的按位查找 GetElem(L,i)&#xff1a;按位查找操作。获取表L中第i个位置的元素的值。 /*查找L中的第i个节点并返回*/ LNode *GetElm(LinkList L,int i) { /*位置不合法返回NULL*/ if(i<0) return NULL; /*p指向当前节…...

从0开始学linux韦东山教程第四章问题小结(1)

本人从0开始学习linux&#xff0c;使用的是韦东山的教程&#xff0c;在跟着课程学习的情况下的所遇到的问题的总结,理论虽枯燥但是是基础。说实在的越看视频越感觉他讲的有点乱后续将以他的新版PDF手册为中心&#xff0c;视频作为辅助理解的工具。参考手册为嵌入式Linux应用开发…...

TYUT-企业级开发教程-第三章

JAVAWEB的三大组件 在 Spring Boot 项目中&#xff0c;会自动将 Spring 容器中的 Servlet 、 Filter 、 Listener 实例注册为 Web 服务器中对应的组件。因此&#xff0c;可以将自定义的 Java Web 三大组件作为 Bean 添加到 Spring 容器中&#xff0c;以实现组件的注册。使用 S…...

【数据结构】2-3-2 单链表的插入删除

数据结构知识点合集 知识点 按位序插入带头节点链表 ListInsert(&L,i,e)&#xff1a;插入操作。在表L中的第i个位置上插入指定元素e&#xff1b;找到第 i-1 个结点&#xff0c;将新结点插入其后 。 /*在带头节点的单链表L的第i个位置插入元素e*/ bool ListInsert(LinkList …...

spark-配置yarn模式

1.上传并解压spark-3.1.1-bin-hadoop3.2.tgz &#xff08;/opt/software) 解压的命令是&#xff1a;tar -zxvf spark-3.3.1-bin-hadoop3.tgz -C /opt/module (cd /opt/software 进入software&#xff09; 2.重命名 解压之后的目录为spark-yarn&#xff08;原为spark-3.1.1-…...