SPLADE 在稀疏向量搜索中的原理與應用詳解

今天看到Sentence Transformers v5.0 集成了許多稀疏嵌入模型。為了搞清楚什么稀疏嵌入模型以及應用,查到了SPLADE,比較巧合的是在paper reading分享的時候看到有同學分享了一片ACL 2025的工作也是基于SPLADE去做的。下面結合一些資料分享關于SPLADE 在稀疏向量搜索中的原理以及應用。

主要內容來自:https://www.pinecone.io/learn/splade/

在現代向量搜索出現之前,我們主要采用“傳統”的詞袋模型( Bag of Words, BOW)方法。基于這些方法,我們將待檢索的文檔(例如谷歌的網頁)轉化為一個詞集(即詞袋),進而生成一個表示詞頻的稀疏向量。TF-IDF 和 BM25 是其中典型的算法。

稀疏向量因其高效性、可解釋性和精確的詞語匹配特性,在信息檢索領域曾廣受歡迎。然而,它們遠非完美。

稀疏向量搜索的工作方式與人類的自然表達存在脫節。我們在搜索信息時,通常很難預測目標文檔中會包含哪些確切的詞語。

稠密嵌入模型(Dense Embedding Models)在這方面提供了一定的幫助。利用稠密模型,我們可以基于“語義含義”進行搜索,而非僅僅依賴于詞語匹配。然而,這些模型仍然有不足之處。

稠密嵌入模型需要大量數據進行微調(fine-tune),否則其性能可能不如稀疏方法。這對于難以獲取數據且領域特定術語很重要的小眾領域來說,是一個棘手的問題。

過去曾涌現出各種臨時性的補救方案來應對這些挑戰,包括復雜且(仍然不完美)的兩階段檢索系統,以及查詢和文檔擴展或改寫方法(我們將在后文探討)。然而,這些方案都未能提供真正魯棒、持久的解決方案。

幸運的是,該領域已取得顯著進展,有望結合兩者的優勢。通過混合搜索 (Hybrid Search)技術,稀疏和稠密檢索得以融合;而可學習的稀疏嵌入 (Learnable Sparse Embeddings)則有助于克服傳統稀疏檢索的不足。

本文將深入探討可學習稀疏嵌入領域的最新進展——SPLADE (Sparse Lexical and Expansion model)模型 [1]。


稀疏向量與稠密向量

在信息檢索中,向量嵌入(Vector Embeddings)將文檔和查詢表示為數值向量格式。這種格式使得我們能夠在向量數據庫中通過計算相似度來檢索相似的向量。

稀疏向量和稠密向量是向量表示的兩種不同形式,各有優缺點。

稀疏向量包含很多零值,非零值比例非常小。

TF-IDF 或 BM25 等稀疏向量具有高維度,但包含的非零值非常少(因此得名“稀疏”)。稀疏向量已有數十年的研究歷史,由此產生了緊湊的數據結構和許多專門針對這類向量設計的高效檢索算法。

稠密向量維度較低,但包含豐富信息,大多數或全部維度都包含非零值。這些向量通常由神經網絡模型(如 Transformer)構建,因此能夠表示更抽象的信息,例如文本的語義含義

總的來說,這兩種方法的優缺點可以概括如下表:

稀疏檢索

優點缺點
通常檢索速度更快性能無法相比基線顯著提升
具有良好的基線性能性能無法相比基線顯著提升
不需要模型微調存在詞匯不匹配問題
詞匯精確匹配

密集檢索

優點缺點
通過微調可以超越稀疏檢索性能需要訓練數據,在低資源場景下較困難
可以搜索類似人類的抽象概念泛化能力不強,特別是對于細分術語
支持多模態(文本、圖像、音頻等)和跨模態搜索(如文本到圖像)比稀疏檢索需要更多計算和內存資源
無法精確匹配
不易解釋

理想情況下,我們希望結合兩者的優勢,但這很難實現。

兩階段檢索

一種常見的處理方法是實現兩階段檢索和排序系統(Two-stage Retrieval and Ranking)。在這種方案中,系統使用兩個不同的階段來檢索和排序與給定查詢相關的文檔。

在第一階段,系統使用稀疏檢索方法召回大量候選文檔。然后,這些文檔被傳遞到第二階段,使用稠密模型根據它們與查詢的相關性重新排序結果。

兩階段檢索系統包含一個稀疏檢索器和一個稠密重排序器。

這種方法有一些優點:(1)對完整的文檔集應用稀疏模型進行召回更高效;(2)對召回后較小的文檔集使用較慢的稠密模型進行重排序可以更準確。通過這種方式,我們可以向用戶返回更相關的結果。另一個優點是,重排序階段與檢索系統是分離的,這對于多用途的檢索系統很有幫助。

然而,它并非完美。兩階段的檢索和重排序可能比使用近似搜索算法的單階段系統要慢。擁有兩個階段會帶來更高的工程復雜性。最后,系統的性能依賴于第一階段檢索器能否返回相關的結果;如果第一階段未能召回有用的內容,第二階段的重排序也無濟于事。

改進單階段系統

由于兩階段檢索存在固有的不足,大量研究致力于改進單階段檢索系統

單階段檢索系統。注意,檢索器可以是稀疏、稠密,甚至兩者兼具。

這方面的研究成果之一就是更魯棒、更可學習的稀疏嵌入模型——其中性能最優的模型之一就是 SPLADE。

SPLADE(SparseLexical and Expansion model)模型的理念是:一個預訓練語言模型(如 BERT)可以識別詞語/子詞(在本文中稱為“詞片段”或“詞項”)之間的聯系,并利用這些知識來增強我們的稀疏向量嵌入。

這通過兩種方式實現:它允許我們為不同詞項賦予相關性權重(例如,“the”這樣的詞項權重較低,而“orangutan”等不常用詞權重較高);同時,它支持詞項擴展(Term Expansion):包含除原始文本中出現詞項之外的、相關但不同的備選詞項。

詞項擴展允許我們識別相關但不同的詞項,并在稀疏向量檢索步驟中使用它們。

SPLADE 最顯著的優勢在于它能夠學習詞項擴展,而非僅僅執行詞項擴展。傳統方法需要基于規則進行詞項擴展,這既耗時又本質受限。而 SPLADE可以利用最優秀的語言模型來學習詞項擴展,甚至可以根據句子的上下文對其進行微調。

盡管查詢和文檔包含許多相關的詞項,但由于它們不是“精確匹配”,因此未能被識別。

詞項擴展對于緩解詞匯不匹配問題至關重要——這是查詢和相關文檔之間典型缺乏詞項重疊的現象。

通過對查詢進行詞項擴展,我們將獲得更大的重疊度,因為現在能夠識別相似的詞語。

由于語言的復雜性以及描述同一事物的多種方式,相關文檔與查詢之間可能存在很少甚至沒有詞項重疊,這是可以預期的。詞項擴展正是為了解決這一問題。

SPLADE 嵌入構建過程

SPLADE 構建稀疏嵌入的過程是易于理解的。我們首先使用一個帶有**掩碼語言模型( Masked-Language Modeling, MLM)**頭的 Transformer 模型,例如 BERT。

MLM 是許多 Transformer 常用的預訓練方法。我們可以直接使用一個現成的預訓練 BERT 模型。### BERT 模型介紹

如前所述,我們將使用帶有 MLM 頭的 BERT 模型。如果您熟悉 BERT 和 MLM,那很好;如果不熟悉,下面我們將進行分解。

BERT 是一種流行的 Transformer 模型。與所有 Transformer 一樣,其核心功能是生成信息豐富的詞元嵌入(Token Embeddings)。這具體意味著什么呢?

我們以文本 "Orangutans are native to the rainforests of Indonesia and Malaysia"(猩猩原產于印度尼西亞和馬來西亞的雨林)為例。首先,我們會將這段文本**詞元化(tokenize)**為 BERT 特定的子詞詞元:

text = ("Orangutans are native tothe rainforests of ""Indonesia and Malaysia"
)# create the tokens that will be input into the model
tokens = tokenizer(text, returntensors="pt")
tokens
{'inputids': tensor([[  101,  2030,  5654, 13210,  3619,  2024,  3128,2000,  1996, 18951,\2015,  1997,  6239,  1998,  6027,   102]]), 'tokentypeids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0]]), 'attentionmask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1]])}
# we transform the inputids to human-readable tokens
tokenizer.convertidstotokens(tokens["inputids"][0])
['[CLS]',\'or',\'##ang',\'##uta',\'##ns',\'are',\'native',\'to',\'the',\'rainforest',\'##s',\'of',\'indonesia',\'and',\'malaysia',\'[SEP]']

詞元 ID 被映射到嵌入矩陣中學習到的詞元嵌入。

這些詞元會與一個**“嵌入矩陣(EmbeddingMatrix)”**相匹配,嵌入矩陣是 BERT 模型的第一層。在這個嵌入矩陣中,我們可以找到學習到的“向量嵌入(Vector Embeddings)”,它們是這些詞語/子詞詞元的“數值表示”。

嵌入矩陣中的向量在有意義的向量空間中分別代表一個詞元。

接下來,原始文本的詞元表示會通過多個**“編碼器塊(Encoder Blocks)”**。這些編碼器塊基于文本的其余上下文,將越來越多的上下文信息編碼到每個向量嵌入中。

在此之后,我們就得到了 Transformer 的**“輸出(Output)”**:信息豐富的向量嵌入。每個嵌入都代表了先前的詞元,但融入了從原始句子中提取的其他詞元向量嵌入中獲取的信息。

通過多個注意力編碼器塊處理初始詞元嵌入,可以編碼更多上下文信息,從而生成信息豐富的嵌入。

這個過程是 BERT 和其他所有 Transformer 模型的核心。然而,Transformer 的強大之處在于,這些信息豐富的向量可以用于眾多不同的任務。通常,我們會給 Transformer 添加一個任務特定的“頭(Head)”,將這些向量轉換為其他形式,例如預測結果或稀疏向量

掩碼語言模型頭 (MLM Head)

MLM 頭 是 BERT 模型常用的眾多“頭”之一。與大多數頭不同,MLM 頭用于 BERT 的初始預訓練階段。

其工作原理是:輸入一個句子,例如 "Orangutans are native to the rainforests of Indonesia and Malaysia"。我們將文本進行詞元化,然后用特殊的 [MASK] 詞元隨機替換部分詞元。

可以使用 [MASK] 詞元屏蔽任何詞語或子詞詞元。

這個經過掩碼處理的詞元序列作為輸入傳遞給 BERT。在另一端,我們將原始句子提供給 MLM 頭。然后,對 BERT 和 MLM 頭進行優化,使其能夠預測被 [MASK] 詞元替換的原始詞語/子詞詞元。

MLM 頭從每個輸出logits 生成一個概率分布。這些概率表示對詞匯表中每個詞元代表 [MASK] 的預測。

為實現這一功能,MLM 頭為每個詞元位置輸出 30522 個值。這30522 個值代表 BERT 的詞匯表大小,并構成一個在詞匯表上的概率分布。激活度最高的值對應的詞元,即為該詞元位置的詞元預測結果。

MLM與稀疏向量

這 30522 個概率分布 wijw{ij}wij? 指示了詞匯表 VVV 中哪些詞語/詞元 jjj 最為重要。MLM 頭為模型輸入的每個詞元 iii 輸出這些分布。

MLM 頭為每個詞元(無論是否被掩碼)提供一個概率分布。這些分布被聚合起來,得到重要性估計。

SPLADE 將所有這些概率分布聚合成一個單一的分布,稱為重要性估計(Importance Estimation) wjw\jwj?。這個重要性估計就是 SPLADE 生成的稀疏向量。我們可以將所有這些概率分布組合成一個單一的分布,它告訴我們詞匯表中的每個詞元與輸入句子的相關性

其計算公式如下:

w j = ∑ i ∈ t log ? ( 1 + ReLU ( w i j ) ) w_j = \sum_{i \in t} \log(1 + \text{ReLU}(w_{ij})) wj?=it?log(1+ReLU(wij?))

其中:

i ∈ t i \in t it:表示輸入詞元集合 t t t 中的每一個詞元 i i i

w i j w_{ij} wij?:表示對于每個詞元 i i i,模型預測的詞匯表 V V V 中所有詞元 j j j 的權重值。

這使得我們能夠識別輸入句子中不存在但相關的詞元。例如,如果我們掩碼了詞語 rainforest(雨林),模型可能會對 jungle(叢林)、land(土地)和 forest(森林)等詞返回較高的預測概率 w j w_j wj?。這些詞語及其相關的概率隨后會在 SPLADE 構建的稀疏向量中得到體現。

這種**“學習到的”查詢/文檔擴展能力,即包含其他相關詞項的能力,是 SPLADE 相較于傳統稀疏方法的一個關鍵優勢**。它基于學習到的詞項關系和上下文,幫助我們最大程度地緩解詞匯不匹配問題。

查詢中的詞項擴展可以大大增加查詢與相關文檔之間的重疊度,從而幫助我們緩解詞匯不匹配問題。

由于許多 Transformer 模型都使用 MLM 進行預訓練,因此有大量模型在預訓練階段學習了 MLM 頭的權重,這些權重可以用于后續的 SPLADE 微調。

SPLADE 的不足之處

SPLADE 是緩解稀疏向量方法常見詞匯不匹配問題的一種優秀方法。然而,我們還需要考慮它的一些局限性。

相較于其他稀疏方法,使用SPLADE 進行檢索速度相對較慢。這主要有三個原因:

  1. SPLADE 查詢和文檔向量中的非零值數量通常多于傳統稀疏向量,而現有的稀疏檢索系統并未針對這一點進行優化。
  2. 非零值的分布偏離了傳統稀疏檢索系統所預期的分布,這也會導致速度變慢。
  3. 大多數稀疏檢索系統不原生支持 SPLADE 向量,這意味著我們必須執行多步預處理和后處理,例如權重離散化等。

幸運的是,所有這些問題都有解決方案。針對原因 (1),SPLADE 的作者在模型的后續版本 (SPLADEv2) 中解決了這個問題,該版本最小化了查詢向量中的非零值數量 [2]。

減少查詢向量中的非零值數量是通過兩個步驟實現的。首先,通過對原始池化策略進行最大池化(Max Pooling)修改,提高了 SPLADE 文檔編碼的性能:

wj=maxi∈tlog(1+ReLU(wij))w\j = max{i \in t}log(1 + ReLU(w{ij}))wj?=maxi∈t?log(1+ReLU(wij?))

其次,將詞項擴展僅限于文檔編碼。得益于改進后的文檔編碼性能,即使去掉了查詢擴展,性能依然優于原始的 SPLADE 模型。

原因 (2) 和 (3) 則可以通過使用 Pinecone 向量數據庫解決。(2) 的解決方案在于 Pinecone 的檢索引擎從頭設計時就不依賴數據分布。Pinecone 支持實數值的稀疏向量,這意味著 SPLADE 向量天然就能得到支持。

SPLADE 實現示例

實現 SPLADE 有兩種選擇:直接使用 Hugging Face 的 Transformer 和 PyTorch,或者使用封裝程度更高的官方 SPLADE 庫。我們將演示這兩種方法,先從 Hugging Face 和 PyTorch 的實現開始,以便理解其內部工作原理。

使用Hugging Face 和 PyTorch

首先,安裝所有必需的庫:

!pip install -U transformers torch

然后,初始化 BERT 的分詞器(Tokenizer)和帶有掩碼語言模型(MLM)頭的 BERT 模型。我們加載 naver/splade-cocondenser-ensembledistil 中經過微調的 SPLADE 模型權重。

from transformers import AutoModelForMaskedLM, AutoTokenizermodelid = 'naver/splade-cocondenser-ensembledistil'tokenizer = AutoTokenizer.frompretrained(modelid)
model = AutoModelForMaskedLM.frompretrained(modelid)

接下來,我們可以創建一個輸入文檔文本 text,對其進行詞元化,并通過 model 處理,以生成 MLM 頭的輸出 logits。

tokens = tokenizer(text, returntensors='pt')
output = model(**tokens)
output
MaskedLMOutput(loss=None, logits=tensor([[[ -6.9833,  -8.2131,  -8.1693,  ...,  -8.1552,  -7.8168,  -5.8152],\[-13.6888, -11.7828, -12.5595,  ..., -12.4415, -11.5789, -12.0632],\[ -8.7075,  -8.7019,  -9.0092,  ...,  -9.1933,  -8.4834,  -6.8165],\...,\[ -5.1051,  -7.7245,  -7.0402,  ...,-7.5713,  -6.9855,  -5.0462],\[-23.5020, -18.8779, -17.7931,  ..., -18.2811, -17.2806, -19.4826],\[-21.6329,-17.7142, -16.6525,  ..., -17.1870, -16.1865, -17.9581]]],gradfn=<ViewBackward0>), hiddenstates=None, attentions=None)
output.logits.shape
torch.Size([1, 91, 30522])

我們得到了 91 個概率分布,每個分布的維度是 30522。要將其轉換為 SPLADE 稀疏向量,我們執行以下操作:

importtorchvec = torch.max(torch.log(1 + torch.relu(output.logits)) * tokens.attentionmask.unsqueeze(-1),
dim=1)[0].squeeze()vec.shape
torch.Size([30522])
vec
tensor([0., 0., 0.,  ..., 0.,0., 0.], gradfn=<SqueezeBackward0>)

由于我們的向量是稀疏的,我們可以將其轉換為更緊湊的字典格式,只保留非零值的位置和權重。

cols = vec.nonzero().squeeze().cpu().tolist()
print(f"非零值數量: {len(cols)}")# extract the non-zero values
weights = vec[cols].cpu().tolist()
# use to create a dictionary of token ID to weight
sparsedict = dict(zip(cols, weights))
sparsedict
非零值數量: 174```

{1000: 0.6246446967124939,
1039: 0.45678916573524475,
1052: 0.3088974058628082,
1997: 0.15812619030475616,
1999: 0.07194626331329346,
2003: 0.6496524810791016,
2024: 0.9411943554878235,
…,
29215: 0.3594200909137726,
29278: 2.276832342147827}


這是稀疏向量的最終格式,但還不太易于解釋。我們可以將詞元 ID 鍵轉換為人類可讀的純文本詞元。操作如下:```python
# extract the ID position to text token mappings
idx2token = {idx: token for token, idx in tokenizer.getvocab().items()
}
# map tokenIDs to human-readable tokens
sparsedicttokens = {idx2token[idx]: round(weight, 2) for idx, weight in zip(cols, weights)
}
# sort so we cansee most relevant tokens first
sparsedicttokens = {k: v for k, v in sorted(sparsedicttokens.items(),key=lambda item: item[1],reverse=True)
}
sparsedicttokens
{'pc': 3.02,'lace': 2.95,'programmed': 2.36,'##for': 2.28,'madagascar': 2.26,'death': 1.96,'##d': 1.95,'lattice':1.81,...,'carter': 0.0,'reg': 0.0}

現在我們可以看到稀疏向量中得分最高的詞元,包括一些重要的領域特定詞項,如 programmed(編程的)、cell(細胞)、lattice(晶格)、regulated(被調節的)等等。

使用 Naver Labs SPLADE 庫

另一個更高級的替代方案是直接使用 SPLADE 官方庫。我們可以通過 pip 安裝它:pip install git+https://github.com/naver/splade.git。然后使用以下代碼初始化相同的模型和構建向量的步驟:


sparsemodelid = 'naver/splade-cocondenser-ensembledistil'sparsemodel = Splade(sparsemodelid, agg='max')
sparsemodel.eval()

我們仍然需要使用 Hugging Face 分詞器對輸入文本進行詞元化以獲取 tokens,然后使用以下代碼創建稀疏向量:

    sparseemb = sparsemodel(dkwargs=tokens)['drep'].squeeze()
sparseemb.shape
torch.Size([30522])

這些嵌入可以像之前使用 Hugging Face 和 PyTorch 方法那樣,被處理成一個更小的稀疏向量字典。最終得到的數據是相同的。

向量比較示例

讓我們看看如何實際比較我們的稀疏向量。我們將定義三個短文本。

texts = [\"Programmed cell death (PCD) is the regulated death of cells within an organism",\"How is thescheduled death of cells within a living thing regulated?",\"Photosynthesis is the process of storing light energy as chemical energy in cells"\
]

像之前一樣,我們使用 tokenizer 對所有文本進行編碼,使用 model 生成輸出 logits,并將詞元級別的向量轉換為單一的稀疏向量。

tokens = tokenizer(texts, returntensors='pt',padding=True, truncation=True
)output = model(**tokens)
# aggregate the token-level vecs and transform to sparse
vecs = torch.max(torch.log(1 + torch.relu(output.logits)) * tokens.attentionmask.unsqueeze(-1), dim=1
)[0].squeeze().detach().cpu().numpy()
vecs.shape
(3, 30522)

現在我們得到了三個30522 維的稀疏向量。為了比較它們,我們可以使用余弦相似度(Cosine Similarity)或點積(Dot Product)計算。使用余弦相似度,我們執行以下操作:

importnumpy as npsim = np.zeros((vecs.shape[0], vecs.shape[0]))for i, vec in enumerate(vecs):sim[i,:] = np.dot(vec, vecs.T) / (np.linalg.norm(vec) * np.linalg.norm(vecs, axis=1))
sim
array([[1.        , 0.54609376, 0.20535842],\[0.54609376, 0.99999988, 0.20411882],\[0.2053584 , 0.20411879, 1.]])

最終得到以下相似度矩陣:

使用上面計算出的相似度值生成的相似度熱力圖。句子 1 和句子 2 共享最高的相似度(對角線除外,它們代表每個句子與自身的比較)。

可以看到,兩個內容相似的句子(句 1 和句 2)的相似度得分自然高于與第三個不相關句子(句 3)的相似度得分。

—以上便是對 SPLADE 學習型稀疏嵌入的介紹。通過 SPLADE,我們可以使用高效的稀疏向量嵌入來表示文本,有助于解決詞匯不匹配問題,同時兼顧精確詞語匹配的能力。

我們也探討了 SPLADE 在傳統檢索系統中的局限性,以及 SPLADEv2 和 Pinecone 這類數據分布無關檢索系統如何克服這些問題。

該領域仍有許多工作可以開展。更多的研究和近期成果表明,結合稠密和稀疏表示的混合搜索 (Hybrid Search)索引能帶來更多優勢。通過這些以及其他眾多進展,我們可以看到向量搜索正變得越來越精確和易用。


參考文獻

[1] T. Formal, B. Piwowarski, S. Clinchant, SPLADE: Sparse Lexical and Expansion Model for First Stage Ranking (2021), SIGIR 21

[2] T. Formal, C. Lassance, B. Piwowarski, S. Clinchant, SPLADE v2: Sparse Lexical and Expansion Model for Information Retrieval (2021)

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

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

相關文章

wpf的Binding之UpdateSourceTrigger

前言 在wpf界面開發中&#xff0c;Binding的源和目標之間可以通過Mode來決定數據的傳遞方向&#xff0c;同時數據傳遞時的觸發條件也是可以有多種情況&#xff0c;多種情況由UpdateSourceTrigger屬性來控制&#xff0c;該屬性有Default、Explicit、LostFocus、PropertyChanged…

突破性進展:超短等離子體脈沖實現單電子量子干涉,為飛行量子比特奠定基礎

關鍵詞&#xff1a;量子計算、電子干涉測量、等離子體脈沖、馬赫-曾德爾干涉儀、非絕熱量子操控 研究背景 在量子計算領域&#xff0c;飛行量子比特&#xff08;flying qubits&#xff09;因其動態傳播特性和通過庫侖相互作用直接糾纏的能力&#xff0c;成為替代光子量子比特的…

Java調用百度地圖天氣查詢服務獲取當前和未來天氣-以貴州省榕江縣為例

目錄 前言 一、百度天氣查詢服務 1、天氣查詢服務 2、查詢API簡介 二、UniHttp集成天氣查詢服務 1、定義訪問接口 2、業務集成調用 三、天氣檢索成果 1、IDE檢索結果輸出 2、互聯網天氣對比 四、總結 前言 天氣與人們的生活息息相關&#xff0c;無論是日常出行、農業…

Windows Excel文檔辦公工作數據整理小工具

在現代辦公環境中&#xff0c;Excel 是處理數據不可或缺的工具&#xff0c;而 “Excel 工作圈小工具” 則如同為 Excel 量軟件下載地址安裝包 身打造的超級增效器&#xff0c;它是一個集合了大量 Excel 功能的綠色工具軟件&#xff0c;能夠顯著提升你的工作效率。 這款軟件雖然…

Node.js v22.5+ 官方 SQLite 模塊全解析:從入門到實戰

在 Node.js v22.5.0 及更高版本中&#xff0c;node:sqlite 模塊作為內置模塊被引入&#xff0c;為開發者提供了與 SQLite 數據庫交互的官方支持。以下是關于 node:sqlite 模塊的詳細介紹&#xff1a; 一、模塊啟用與導入 啟用方式&#xff1a;node:sqlite 模塊目前處于活躍開…

API接口安全-2:簽名、時間戳與Token如何聯手抵御攻擊

在API接口通信中&#xff0c;數據傳輸的安全性至關重要。無論是前端與后端的交互&#xff0c;還是企業間的接口對接&#xff0c;一旦缺乏有效的安全校驗&#xff0c;攻擊者可能通過抓包篡改參數&#xff08;如修改訂單金額&#xff09;、重放攻擊&#xff08;重復提交支付請求&…

Pull Request記錄與Git commit簽名

Pull Request記錄 好久沒有pull request了&#xff0c;淺淺記錄一下流程 &#xff1a;Fork 原項目&#xff08;如果你沒有寫權限&#xff09;&#xff1a;打開原項目主頁&#xff08;例如&#xff1a;github.com/your-professor/research-topic&#xff09;&#xff0c;點擊右…

如何在C++交易系統中集成高性能回測與模擬撮合

DolphinDB 的高性能行情回放與模擬撮合引擎插件&#xff0c;為量化交易者提供了低延遲、高吞吐量的策略驗證解決方案。對于已構建 C 回測框架的機構而言&#xff0c;直接在現有系統中集成撮合引擎&#xff0c;既能復用既有基礎設施&#xff0c;又能獲得 DolphinDB 的極速計算優…

【Laravel】 Laravel 智能驗證規則生成器

Laravel 智能驗證規則生成器:企業級增強方案 <?phpnamespace App\Services\Validation;use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; use Illuminate\Validation\…

講基于優化的 IMU 與視覺信息融合

目錄 視覺 SLAM 里的 Bundle Adjustment 問題 最小二乘基礎概念 迭代下降法求解:下降法 最速下降法和牛頓法 阻尼法 非線性最小二乘 Gauss-Newton 和 LM 魯棒核函數的實現 VIO 殘差函數的構建 視覺重投影誤差 IMU 測量值積分 狀態誤差線性遞推公式的推導 基于誤差隨時間變化的…

洛谷P1107 [BJWC2008] 雷濤的小貓

洛谷P1107 [BJWC2008] 雷濤的小貓 洛谷題目傳送門 題目背景 原最大整數參見 P1012 題目描述 雷濤同學非常的有愛心&#xff0c;在他的宿舍里&#xff0c;養著一只因為受傷被救助的小貓&#xff08;當然&#xff0c;這樣的行為是違反學生宿舍管理條例的&#xff09;。在他的…

ROS2---話題重映射

一、話題重映射的基本概念 在 ROS2&#xff08;Robot Operating System 2&#xff09;中&#xff0c;話題重映射&#xff08;Topic Remapping&#xff09; 是一種靈活的機制&#xff0c;允許用戶在不修改代碼的情況下&#xff0c;改變節點發布或訂閱的話題名稱。這一機制在多機…

IOday4——7.3

1.思維導圖 2.創建一個分支線程&#xff0c;在主線程中拷貝文件的前一部分&#xff0c;主線程拷貝文件的后一部分。 3.解讀代碼 info1 from child process_1 info2 from child process_1 info1 from child process_2 info1 from parent process 4.解讀代碼&#xff0c;打印…

[特殊字符] Excel 提取+圖片批量插入 | Python 自動化生成稽查報告 Word 模板

本篇教程展示如何利用 Python&#xff0c;實現從 Excel 中提取稽查問題數據&#xff0c;并將對應圖片按順序插入到 Word 模板表格里&#xff0c;最終生成一份圖文并茂的稽查報告。 目錄 &#x1f4dd; Step 1&#xff1a;從 Excel 提取稽查問題數據 &#x1f5bc; Step 2&am…

【libm】 7 雙精度正弦函數 (k_sin.rs)

一、源碼 這段代碼實現了一個高精度的正弦函數計算核心&#xff08;kernel sin function&#xff09;&#xff0c;用于計算在區間約[-π/4, π/4]內的正弦值。 // origin: FreeBSD /usr/src/lib/msun/src/k_sin.c // // // Copyright (C) 1993 by Sun Microsystems, Inc. Al…

c++ 的標準庫 --- std::

在 C 的標準庫&#xff08;std&#xff09;里&#xff0c;除了 std::string&#xff0c;還有很多常用的類型和工具。下面列舉一些最常用的&#xff1a; 常用的 std:: 標準庫類型 1. 容器類&#xff08;用來存放一組數據&#xff09; std::vector??// 動態數組&#xff0c;類…

用 PyTorch 構建液態神經網絡(LNN):下一代動態深度學習模型

引言 在深度學習領域&#xff0c;研究人員不斷探索更接近生物神經系統工作方式的模型。液態神經網絡(Liquid Neural Networks, LNN)正是這樣一種受生物神經元動態特性啟發的創新架構。本文將帶你了解LNN的核心概念&#xff0c;并展示如何使用PyTorch實現這種前沿模型。 一、什…

取消latex Beamer 中,右下角的導航按鈕

取消 Beamer 右下角的導航按鈕 在 Beamer 中,右下角的導航按鈕(如上一頁、下一頁、目錄等)是由主題(如 Boadilla)自動添加的。要移除它們,可以通過以下方法實現: 方法 1:使用 \setbeamertemplate{navigation symbols}{}(推薦) 在導言區(\begin{document} 之前)添…

LLaMA-Factory 單卡后訓練微調Qwen3完整腳本

LLaMA-Factory 單卡后訓練微調Qwen3完整腳本 flyfish 使用說明 將下面代碼保存為 train_single_gpu.sh 修改腳本中的以下參數&#xff1a; MODEL_PATH&#xff1a;模型路徑 DS_CONFIG_PATH&#xff1a;DeepSpeed配置文件路徑 OUTPUT_PATH&#xff1a;輸出目錄路徑 --dataset…

AI自動化神器-DroidRun使用體驗

引言 DroidRun 是一個強大的框架&#xff0c;用于通過 LLM 代理控制 Android 設備。它允許您使用自然語言命令自動化 Android 設備交互。 特點 使用自然語言命令控制 Android 設備 支持多個 LLM 提供商(OpenAI、Anthropic、Gemini) 易于使用的 CLI 用于自定義自動化的可擴…