手撕LLM(二):從源碼出發,探索LoRA加載、推理全流程

? ? ? ?接上回接著說,前面我們通過分析源碼,了解了大模型推理的詳細流程,包括提示詞從輸入,到對話模版包裝,到tokenID轉換,到Embedding詞向量轉換;通過大模型推理,再將大模型輸出進行最后一個token-tensor提取;再到模型的后處理,又包括多次Softmax計算、Top_p采樣、解碼為文本數據等;中間還穿插了對模型結構的分析;這樣一套下來,我們對大模型就有了一個比較清晰的認識,那接下來我們就進入下一個環節——探索LLM外掛LoRA的推理流程。

? ? ? ?說到LoRA,想必大家也不陌生,甚至還可以說出它的基本原理和實現的思路,比如它可以降低訓練成本是因為它減少了可訓練參數,可訓練參數可減少又是因為矩陣的向量冗余,可用低階矩陣來代替;再比如它可以外掛在指定的預訓練權重上不改變原模型的權重;但具體它是如何外掛的、哪些權重層可以外掛、如何將原權重和其對應的LoRA外掛一一對應呢?對于在寫這篇博客之前的我來說真的是一頭霧水,有點紙上談兵,真刀真槍干的時候就拉垮了。

? ? ? ?為了弄清LoRA在代碼上的具體實現,而不只是知道其原理,其優點;還是以Minimind項目為基礎,從代碼入手,探索其具體的實現流程。

一、LoRA

? ? ? ?此博客的主題是LoRA,就先從原理上‘紙上談兵’,分享一下我對LoRA的一些淺顯的認識,如有不準確、不恰當、不對的地方,還請各位大神指正;

? ? ? ?首先,模型的預訓練權重其實就是一堆標量組成的向量矩陣,LoRA也是一樣,它也是矩陣;說到矩陣肯定就離不開線性代數,我們大學線代里學了一個詞叫極大線性無關組,說的就是一個矩陣中所包含的向量不一定是相互獨立的,可能某幾個向量的線性組合就可以表示另外一個向量,我們需要在這個矩陣中找到一組向量,使得這組向量不可以被矩陣中的其他向量表示出來,我們就說這組向量是該矩陣的一個極大線性無關組,也就是矩陣的秩,秩的個數就是極大線性無關組的向量個數,同樣也可以反過來說這組極大線性無關組可以表示該矩陣,這個就是LoRA的核心;

? ? ? ?然后,我們再說回LoRA,LoRA由A、B兩個低階矩陣組成,用來替代原高階權重矩陣,同時有一個超參叫rank,這個參數定義的是A、B矩陣較小的那個維度,就類似于原權重矩陣秩的概念,原理同上,就是原高階權重矩陣(k,k)其實它內部的向量或者信息大概率是冗余的,存在一個極大線性無關組可以替代,假設這個極大線性無關組個數為n(n<k),但又要保持該層的輸入輸出維度保持不變,所以可以由兩個(k,n)維的矩陣相乘來替換,然后針對該層的可訓練參數就又原來的k的平方變為2倍的k*n,若使得2*k*n小于k方,n小于二分之一k即可,而在一般的權重層,其維度都是四位數,但rank的超參一般指定8或者16等小數值,遠小于其一半,所以可以起到降低訓練參數的目的,同時結合極大線性無關的概念,其代替的效果也不會交原權重有較大的差異;

二、具體實現

? ? ? ?上面我們說了一下LoRA實現的原理及背后簡單的數學邏輯,下面就以Minimind項目為基礎,通過代碼來探索它的具體實現,該項目的環境安裝和預訓練模型權重下載大家自行完成,這里就不再演示了;

2.1 代碼解析

? ? ? ?我們先簡單看一下代碼的架構,從eval_model.py中,我們可以找到在init_model(args)函數中有LoRA的身影,這里有兩個函數調用,apply_lora()和oad_lora()分別用來添加LoRA層和加載LoRA權重,我們分別來看這兩個函數。

# eval_model.py的init_model()函數def init_model(args):tokenizer = AutoTokenizer.from_pretrained('./model/minimind_tokenizer')if args.load == 0:moe_path = '_moe' if args.use_moe else ''modes = {0: 'pretrain', 1: 'full_sft', 2: 'rlhf', 3: 'reason'}# ckp = f'./{args.out_dir}/{modes[args.model_mode]}_{args.dim}{moe_path}.pth'ckp = f'../Weights/MiniMind2-PyTorch/{modes[args.model_mode]}_{args.dim}{moe_path}.pth'model = MiniMindLM(LMConfig(dim=args.dim,n_layers=args.n_layers,max_seq_len=args.max_seq_len,use_moe=args.use_moe))state_dict = torch.load(ckp, map_location=args.device)model.load_state_dict({k: v for k, v in state_dict.items() if 'mask' not in k}, strict=True)if args.lora_name != 'None':apply_lora(model)load_lora(model, f'./{args.out_dir}/lora/{args.lora_name}_{args.dim}.pth')else:transformers_model_path = '../Weights/MiniMind2'tokenizer = AutoTokenizer.from_pretrained(transformers_model_path)model = AutoModelForCausalLM.from_pretrained(transformers_model_path, trust_remote_code=True)print(f'MiniMind模型參數量: {sum(p.numel() for p in model.parameters() if p.requires_grad) / 1e6:.2f}M(illion)')return model.eval().to(args.device), tokenizer

2.1.1??apply_lora()

# model/model_lora.pydef apply_lora(model, rank=16):for name, module in model.named_modules():if isinstance(module, nn.Linear) and module.weight.shape[0] == module.weight.shape[1]:lora = LoRA(module.weight.shape[0], module.weight.shape[1], rank=rank).to(model.device)setattr(module, "lora", lora)original_forward = module.forward# 顯式綁定def forward_with_lora(x, layer1=original_forward, layer2=lora):return layer1(x) + layer2(x)module.forward = forward_with_lora

? ? ? ?這個API的目的將是在model對象里面添加lora結構,代碼很簡單,首先該API接收model對象參數傳遞:
1)通過named_modules()遍歷模型中的所有模塊(包括子模塊),并獲取它們的名稱(name)和對應的模塊對象(module);
2)對模型對象符合nn.Linear類別且權重為方形矩陣的層進行LoRA層添加;
3)接下來就是定義LoRA層,這個我們在2.1.2詳解;
4)通過setattr()函數為該層添加lora屬性;
5)獲取該層的前向推理original_forward;
6)通過forward_with_lora()函數將原forward和添加的lora層并行運行,輸出結果疊加;

2.1.2?class LoRA(nn.Module)

# model/model_lora.py# 定義Lora網絡結構
class LoRA(nn.Module):def __init__(self, in_features, out_features, rank):super().__init__()self.rank = rank  # LoRA的秩(rank),控制低秩矩陣的大小self.A = nn.Linear(in_features, rank, bias=False)  # 低秩矩陣Aself.B = nn.Linear(rank, out_features, bias=False)  # 低秩矩陣B# 矩陣A高斯初始化self.A.weight.data.normal_(mean=0.0, std=0.02)# 矩陣B全0初始化self.B.weight.data.zero_()def forward(self, x):return self.B(self.A(x))

這是一個通過pytorch自定義的一個標準的LoRA層,先看它包括哪些子層:
1)可以看到定義了兩個全鏈接層A、B;
2)同時指定了rank的大小,就是第一節中的超參rank;
3)下面采用不同方式初始化了A、B;

接著我們在看LoRA層的推理流程:
1)通過forward()函數,我們可以看到輸入張量先經過A矩陣,再接結果輸入到B矩陣,最后返回LoRA層的輸出結果;

2.1.3?load_lora()?

# model/model_lora.pydef load_lora(model, path):state_dict = torch.load(path, map_location=model.device)for name, module in model.named_modules():if hasattr(module, 'lora'):lora_state = {k.replace(f'{name}.lora.', ''): v for k, v in state_dict.items() if f'{name}.lora.' in k}module.lora.load_state_dict(lora_state)

? ? ? ?這段API目的就是將已經訓練好的LoRA權重文件讀取并加載到model中對應的層上,步驟也很簡單,API接收添加LoRA結構的model對象和本地LoRA權重文件路徑:
1)?通過torch.load()函數將權重文件加載到內存,state_dict為一個字典迭代器;
2)遍歷model,獲取model中的層名以及層對象;
3)通過hasattr()函數判斷module子層對象有沒有lora屬性;
4)對于有lora屬性的子層,通過其層名稱找到對應state_dict中的權重張量;
5)通過load_state_dict()函數將權重張量賦值到lora層;

這樣我們就可以得到包含lora結構以及加載上lora權重的model對象啦;

2.2 具體實現

? ? ? ?和之前一樣,依然在eval_model.py同級目錄創建一個jujupyterNotebook文件,我們自己實操一下LoRA的添加過程;

2.2.1 導包

代碼:

import argparse
import random
import time
import numpy as np
import torch
import warnings
from transformers import AutoTokenizer, AutoModelForCausalLM
from model.model import MiniMindLM
from model.LMConfig import LMConfig
from model.model_lora import *warnings.filterwarnings('ignore')

2.2.2 定義超參

代碼:

class ARG():def __init__(self):self.lora_name = 'None'self.out_dir = 'out'self.temperature = 0.85self.top_p = 0.85self.device = 'cpu'self.dim = 512self.n_layers = 8self.max_seq_len = 8192self.use_moe = Falseself.history_cnt = 0self.stream = Trueself.load = 0self.model_mode = 1

2.2.3?定義模型初始化API

代碼:

def init_model(args):if args.load == 0:moe_path = '_moe' if args.use_moe else ''modes = {0: 'pretrain', 1: 'full_sft', 2: 'rlhf', 3: 'reason'}# ckp = f'./{args.out_dir}/{modes[args.model_mode]}_{args.dim}{moe_path}.pth'ckp = f'../Weights/MiniMind2-PyTorch/{modes[args.model_mode]}_{args.dim}{moe_path}.pth'model = MiniMindLM(LMConfig(dim=args.dim,n_layers=args.n_layers,max_seq_len=args.max_seq_len,use_moe=args.use_moe))state_dict = torch.load(ckp, map_location=args.device)model.load_state_dict({k: v for k, v in state_dict.items() if 'mask' not in k}, strict=True)else:transformers_model_path = '../Weights/MiniMind2'tokenizer = AutoTokenizer.from_pretrained(transformers_model_path)model = AutoModelForCausalLM.from_pretrained(transformers_model_path, trust_remote_code=True)print(f'MiniMind模型參數量: {sum(p.numel() for p in model.parameters() if p.requires_grad) / 1e6:.2f}M(illion)')return model

2.2.4? 初始化超參、模型

? ? ? ?從遍歷出來的model的子層中我們可以清晰的看到模型的結果,以及原始的model對象中不包含lora層;

代碼:

args = ARG()
model = init_model(args)
# 遍歷模型中的所有模塊(包括子模塊),并獲取它們的名稱和對應的模塊對象
for name, module in model.named_modules():print(f"Module Name: {name}")print(f"Module Type: {type(module)}")print(hasattr(module, 'lora'))if hasattr(module, 'weight') and module.weight is not None:print(f"  Weight Shape: {module.weight.shape}")if hasattr(module, 'bias') and module.bias is not None:print(f"  Bias Shape: {module.bias.shape}")print("-" * 40)

輸出結果:?

MiniMind模型參數量: 25.83M(illion)
Module Name: 
Module Type: <class 'model.model.MiniMindLM'>
False
----------------------------------------
Module Name: tok_embeddings
Module Type: <class 'torch.nn.modules.sparse.Embedding'>
FalseWeight Shape: torch.Size([6400, 512])
----------------------------------------
Module Name: dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
Module Name: layers
Module Type: <class 'torch.nn.modules.container.ModuleList'>
False
----------------------------------------
Module Name: layers.0
Module Type: <class 'model.model.MiniMindBlock'>
False
----------------------------------------
Module Name: layers.0.attention
Module Type: <class 'model.model.Attention'>
False
----------------------------------------
Module Name: layers.0.attention.wq
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([512, 512])
----------------------------------------
Module Name: layers.0.attention.wk
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([128, 512])
----------------------------------------
Module Name: layers.0.attention.wv
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([128, 512])
----------------------------------------
Module Name: layers.0.attention.wo
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([512, 512])
----------------------------------------
Module Name: layers.0.attention.attn_dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
Module Name: layers.0.attention.resid_dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
Module Name: layers.0.attention_norm
Module Type: <class 'model.model.RMSNorm'>
FalseWeight Shape: torch.Size([512])
----------------------------------------
Module Name: layers.0.ffn_norm
Module Type: <class 'model.model.RMSNorm'>
FalseWeight Shape: torch.Size([512])
----------------------------------------
Module Name: layers.0.feed_forward
Module Type: <class 'model.model.FeedForward'>
False
----------------------------------------
Module Name: layers.0.feed_forward.w1
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([1408, 512])
----------------------------------------
Module Name: layers.0.feed_forward.w2
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([512, 1408])
----------------------------------------
Module Name: layers.0.feed_forward.w3
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([1408, 512])
----------------------------------------
Module Name: layers.0.feed_forward.dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
Module Name: layers.1
Module Type: <class 'model.model.MiniMindBlock'>
False
----------------------------------------
Module Name: layers.1.attention
Module Type: <class 'model.model.Attention'>
False
----------------------------------------
Module Name: layers.1.attention.wq
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([512, 512])
----------------------------------------
Module Name: layers.1.attention.wk
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([128, 512])
----------------------------------------
Module Name: layers.1.attention.wv
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([128, 512])
----------------------------------------
Module Name: layers.1.attention.wo
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([512, 512])
----------------------------------------
Module Name: layers.1.attention.attn_dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
Module Name: layers.1.attention.resid_dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
Module Name: layers.1.attention_norm
Module Type: <class 'model.model.RMSNorm'>
FalseWeight Shape: torch.Size([512])
----------------------------------------
Module Name: layers.1.ffn_norm
Module Type: <class 'model.model.RMSNorm'>
FalseWeight Shape: torch.Size([512])
----------------------------------------
Module Name: layers.1.feed_forward
Module Type: <class 'model.model.FeedForward'>
False
----------------------------------------
Module Name: layers.1.feed_forward.w1
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([1408, 512])
----------------------------------------
Module Name: layers.1.feed_forward.w2
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([512, 1408])
----------------------------------------
Module Name: layers.1.feed_forward.w3
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([1408, 512])
----------------------------------------
Module Name: layers.1.feed_forward.dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
.....

2.2.5 定義LoRA層

代碼:

# 定義Lora網絡結構
class LoRA(nn.Module):def __init__(self, in_features, out_features, rank):super().__init__()self.rank = rank  # LoRA的秩(rank),控制低秩矩陣的大小self.A = nn.Linear(in_features, rank, bias=False)  # 低秩矩陣Aself.B = nn.Linear(rank, out_features, bias=False)  # 低秩矩陣B# 矩陣A高斯初始化self.A.weight.data.normal_(mean=0.0, std=0.02)# 矩陣B全0初始化self.B.weight.data.zero_()def forward(self, x):return self.B(self.A(x))

2.2.6 定義LoRA添加API

代碼:

def apply_lora(model, rank=16):for name, module in model.named_modules():if isinstance(module, nn.Linear) and module.weight.shape[0] == module.weight.shape[1]:lora = LoRA(module.weight.shape[0], module.weight.shape[1], rank=rank).to(model.device)setattr(module, "lora", lora)original_forward = module.forward# 顯式綁定def forward_with_lora(x, layer1=original_forward, layer2=lora):return layer1(x) + layer2(x)module.forward = forward_with_lora

?2.2.7 添加LoRA層

? ? ? ?當添加完LoRA層在此遍歷model子層,我們可以看到在transformer模塊的Query權重層添加了LoRA層,因為Query權重層符合nn.Linear類別并且它的權重尺寸是512*512的方形;

代碼:

apply_lora(model)
# 遍歷模型中的所有模塊(包括子模塊),并獲取它們的名稱和對應的模塊對象
for name, module in model.named_modules():print(f"Module Name: {name}")print(f"Module Type: {type(module)}")print(hasattr(module, 'lora'))if hasattr(module, 'weight') and module.weight is not None:print(f"  Weight Shape: {module.weight.shape}")if hasattr(module, 'bias') and module.bias is not None:print(f"  Bias Shape: {module.bias.shape}")print("-" * 40)

輸出結果:

Module Name: 
Module Type: <class 'model.model.MiniMindLM'>
False
----------------------------------------
Module Name: tok_embeddings
Module Type: <class 'torch.nn.modules.sparse.Embedding'>
FalseWeight Shape: torch.Size([6400, 512])
----------------------------------------
Module Name: dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
Module Name: layers
Module Type: <class 'torch.nn.modules.container.ModuleList'>
False
----------------------------------------
Module Name: layers.0
Module Type: <class 'model.model.MiniMindBlock'>
False
----------------------------------------
Module Name: layers.0.attention
Module Type: <class 'model.model.Attention'>
False
----------------------------------------
Module Name: layers.0.attention.wq
Module Type: <class 'torch.nn.modules.linear.Linear'>
TrueWeight Shape: torch.Size([512, 512])
----------------------------------------
Module Name: layers.0.attention.wq.lora
Module Type: <class '__main__.LoRA'>
False
----------------------------------------
Module Name: layers.0.attention.wq.lora.A
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([16, 512])
----------------------------------------
Module Name: layers.0.attention.wq.lora.B
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([512, 16])
----------------------------------------
Module Name: layers.0.attention.wk
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([128, 512])
----------------------------------------
Module Name: layers.0.attention.wv
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([128, 512])
----------------------------------------
Module Name: layers.0.attention.wo
Module Type: <class 'torch.nn.modules.linear.Linear'>
TrueWeight Shape: torch.Size([512, 512])
----------------------------------------
Module Name: layers.0.attention.wo.lora
Module Type: <class '__main__.LoRA'>
False
----------------------------------------
Module Name: layers.0.attention.wo.lora.A
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([16, 512])
----------------------------------------
Module Name: layers.0.attention.wo.lora.B
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([512, 16])
----------------------------------------
Module Name: layers.0.attention.attn_dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
Module Name: layers.0.attention.resid_dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
Module Name: layers.0.attention_norm
Module Type: <class 'model.model.RMSNorm'>
FalseWeight Shape: torch.Size([512])
----------------------------------------
Module Name: layers.0.ffn_norm
Module Type: <class 'model.model.RMSNorm'>
FalseWeight Shape: torch.Size([512])
----------------------------------------
Module Name: layers.0.feed_forward
Module Type: <class 'model.model.FeedForward'>
False
----------------------------------------
Module Name: layers.0.feed_forward.w1
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([1408, 512])
----------------------------------------
Module Name: layers.0.feed_forward.w2
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([512, 1408])
----------------------------------------
Module Name: layers.0.feed_forward.w3
Module Type: <class 'torch.nn.modules.linear.Linear'>
FalseWeight Shape: torch.Size([1408, 512])
----------------------------------------
Module Name: layers.0.feed_forward.dropout
Module Type: <class 'torch.nn.modules.dropout.Dropout'>
False
----------------------------------------
......

2.2.8 加載LoRA權重

? ? ? ?由于我本地沒有訓練好的適配的LoRA權重文件,所以這里就先保留;截止到此模型中的LoRA層的權重還是初始化的權重張量;

三、總結

? ? ? ?至此,我們就獲得到了添加了LoRA層的模型對象;通過此博客,我們回顧了LoRA的本質、原理以及其背后的數學邏輯,并通過代碼完成了LoRA層的定義、通過屬性添加完成了指定層的lora屬性添加、通過顯式綁定完成了指定層的推理流程重定義等操作,可以說不管是理論還是實踐,我們都加深了對LoRA的理解;如果此博客對你有所幫助,請點一個贊,如果還想繼續跟著這個系列一起學習更多大模型的實踐,可以點一個關注,我將不斷學習,持續更新該系列內容,謝謝~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76951.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76951.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76951.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WPS宏開發手冊——常見問題

目錄 系列文章6、常見問題 系列文章 使用、工程、模塊介紹 JSA語法 JSA語法練習題 Excel常用Api Excel實戰 常見問題 附錄 6、常見問題 6.1、編輯完宏后會自動保存&#xff0c;下次打開文件會提醒是否啟用宏&#xff0c;點擊啟用會自動加載上次編輯的…

【Android安卓移動計算】實現項目一[模擬器啟動項目]

文章目錄 新建項目項目結構介紹說明程序自動生成&#xff1a;圖片和樣式文件夾&#xff1a;Training1\app\src\main\res\drawable布局文件文件夾&#xff1a;Training1\app\src\main\res\layoutJava文件夾&#xff1a;Training1\app\src\main\java\com\example\training1Androi…

快 速 冪

暴力肯定會超時 3^10 9^5 9*9^4 9*81^2 9*18^2^1 先對b判斷奇偶 偶數&#xff1a;對b/2,對a平方 奇數&#xff1a;先*a,再對a平方&#xff0c;b/2 取余注意&#xff1a;(3^10)%k( 9 * 18^2^1)%k(( 9%k )%k * (18^2^1)%k)%k

網絡釣魚攻擊的威脅和執法部門的作用(第二部分)

執法部門在打擊網絡釣魚中的作用 雖然網絡釣魚可能始于一封欺騙性的電子郵件或短信&#xff0c;但其后果可能遠遠超出個人收件箱的范圍&#xff0c;影響企業、經濟甚至國家安全。隨著網絡釣魚攻擊的規模和復雜性不斷增加&#xff0c;執法機構站在前線&#xff0c;努力預防、調…

Data_Socket和UDP_Socket

Data_Socket 和 UDP_Socket 是兩種不同類型的網絡套接字&#xff0c;它們用于不同的協議和應用場景。以下是它們的主要區別&#xff1a; 協議類型&#xff1a; UDP_Socket&#xff1a;使用的是 UDP&#xff08;User Datagram Protocol&#xff09; 協議&#xff0c;這是一種無連…

2025高頻面試算法總結篇【排序】

文章目錄 直接刷題鏈接直達把數組排成最小的數刪除有序數組中的重復項求兩個排序數組的中位數求一個循環遞增數組的最小值數組中的逆序對如何找到一個無序數組的中位數鏈表排序從一大段文本中找出TOP K 的高頻詞匯 直接刷題鏈接直達 把一個數組排成最大的數 劍指 Offer 45. 把…

模型壓縮技術從零到一

模型壓縮是深度學習中的重要技術&#xff0c;旨在減小模型尺寸和計算需求&#xff0c;特別適合在移動設備或嵌入式系統上部署。 要點 模型壓縮技術可以顯著減小模型尺寸和計算需求&#xff0c;適合資源受限設備。主要技術包括剪枝、量化、知識蒸餾、低秩分解和輕量級模型設計…

浮點數精度問題

目錄 ieee754標準解決方法 和c語言一樣&#xff0c;所有以ieee754標準的語言都有浮點數精度問題&#xff0c;js也有浮點數精度問題&#xff0c;并且因為是弱類型語言這個問題更嚴重&#xff0c;js的Number類型的數據都被視為浮點數 ieee754標準 js的數字類型就相當于c語言doub…

超大規模數據場景(思路)——面試高頻算法題目

目錄 用4KB內存尋找重復元素 從40個億中產生不存在的整數【位】 如果只讓用10MB空間存儲&#xff1f; 初次遍歷 二次遍歷 用2GB內存在20億個整數中查找出現次數最多的數【分塊】 從億萬個URL中查找問題【分塊 堆】 40億個非負整數中找出現兩次的數【位 不過多個位哈】 …

開源身份和訪問管理方案之keycloak(三)keycloak健康檢查(k8s)

文章目錄 開源身份和訪問管理方案之keycloak&#xff08;三&#xff09;keycloak健康檢查啟用運行狀況檢查 健康檢查使用Kubernetes下健康檢查Dockerfile 中 HEALTHCHECK 指令 健康檢查Docker HEALTHCHECK 和 Kubernetes 探針 開源身份和訪問管理方案之keycloak&#xff08;三&…

FATFS備忘

概述 FATFS文件系統可以掛載SD卡也可以掛載FLASH eMMC等設備 SD卡需要格式化為FAT32模式 塊大小默認即可 移植 SD卡 SD卡扇區大小是 512B SD卡 SDIO模式 可以直接在cubeMX里一鍵設置 先設置好SD卡的設置 這個是選擇支持中文 其余是默認 這個是檢測引腳可以留空 當SD卡插入拔出…

唯美社區源碼AM社區同款源碼

源碼介紹 唯美社區源碼AM社區同款源碼 后端修改application.properties文件內容為你的數據庫 前端修改/config/config.js文件內容為你的后端地址 這兩個文件里要修改的地方我已經用中文標注出來了 截圖 源碼免費下載 唯美社區源碼AM社區同款源碼

現代Web應用的多標簽選擇組件:設計哲學與工程實踐

引言&#xff1a;標簽選擇的重要性與挑戰 在信息爆炸時代&#xff0c;標簽系統已成為內容組織的核心基礎設施。研究表明&#xff1a; 使用標簽系統的平臺用戶留存率提高35% 良好的標簽選擇體驗可提升內容發現效率58% 80%的用戶更傾向于使用提供可視化標簽選擇的應用 本文將…

P3799 小 Y 拼木棒

題目背景 上道題中&#xff0c;小 Y 斬了一地的木棒&#xff0c;現在她想要將木棒拼起來。 題目描述 有 n 根木棒&#xff0c;現在從中選 4 根&#xff0c;想要組成一個正三角形&#xff0c;問有幾種選法&#xff1f; 答案對 1097 取模。 輸入格式 第一行一個整數 n。 第…

Perl 條件語句

Perl 條件語句 引言 在編程中&#xff0c;條件語句是執行分支邏輯的關鍵部分。Perl 作為一種強大的腳本語言&#xff0c;提供了豐富的條件語句&#xff0c;使得開發者能夠根據不同的條件執行不同的代碼塊。本文將深入探討 Perl 中的條件語句&#xff0c;包括 if、unless、els…

流量特征分析-蟻劍流量分析

任務&#xff1a; 木馬的連接密碼是多少 這是分析蟻劍流量&#xff0c;可能是網站的&#xff0c;wireshark過濾http 追蹤流http得到 1就是連接密碼 flag{1}黑客執行的第一個命令是什么 取最后的執行命令。base64解密得 除了id不是蟻劍自帶的命令&#xff0c;其他的都是&…

問題1:Sinal 4在開啟PAC檢查的設備崩潰

? 問題信息 硬件不支持PAC(Pointer Authentication),此類錯誤就是signal 11的錯誤,崩潰信息如下: Build fingerprint: google/sdk_gphone64_arm64/emu64a:16/BP22.250221.010/13193326:userdebug/dev-keys Revision: 0 ABI: arm64 Timestamp: 2025-04-06 11:33:13.923…

FreeRTOS移植筆記:讓操作系統在你的硬件上跑起來

一、為什么需要移植&#xff1f; FreeRTOS就像一套"操作系統積木"&#xff0c;但不同硬件平臺&#xff08;如STM32、ESP32、AVR等&#xff09;的CPU架構和外設差異大&#xff0c;需要針對目標硬件做適配配置。移植工作就是讓FreeRTOS能正確管理你的硬件資源。 二、…

【C++11(下)】—— 我與C++的不解之緣(三十二)

前言 隨著 C11 的引入&#xff0c;現代 C 語言在語法層面上變得更加靈活、簡潔。其中最受歡迎的新特性之一就是 lambda 表達式&#xff08;Lambda Expression&#xff09;&#xff0c;它讓我們可以在函數內部直接定義匿名函數。配合 std::function 包裝器 使用&#xff0c;可以…

JavaScript中的Proxy詳解

1. 什么是Proxy&#xff1f; Proxy是ES6引入的一個強大特性&#xff0c;它允許你創建一個對象的代理&#xff0c;從而可以攔截和自定義該對象的基本操作。Proxy提供了一種機制&#xff0c;可以在對象的基本操作&#xff0c;如屬性查找、賦值、枚舉、函數調用等之前或之后執行自…