線性衰減Compatible with Milvus 2.6.x
線性衰減 (Linear Decay) 在您的搜尋結果中創造了一個以絕對零點為終點的直線下降。就像即將發生的事件倒數一樣,相關性逐漸減弱,直到事件結束,線性衰減在項目離開您的理想點時,應用可預測的、穩定的相關性減弱,直到它們完全消失。當您想要一致的衰減率且有明確的分界線時,這種方法是最理想的選擇,可確保超出某個邊界的項目完全被排除在結果之外。
與其他衰減函數不同:
高斯衰減遵循逐漸接近但永遠不會達到零的鐘形曲線
指數衰減保持一個長尾,其相關性極低,並且無限延伸
線性衰減獨一無二地創建了一個明確的終點,因此對於有自然邊界或截止日期的應用程式特別有效。
何時使用線性衰減
線性衰減對以下情況特別有效
使用個案 |
範例 |
為什麼線性效果好 |
|---|---|---|
活動列表 |
音樂會門票平台 |
為太遠的活動建立明確的截止日期 |
限時優惠 |
快銷、促銷 |
確保不會出現過期或即將過期的優惠 |
送貨半徑 |
送餐、快遞服務 |
強制執行硬性地理界限 |
限制年齡的內容 |
約會平台、媒體服務 |
建立確定的年齡門檻 |
在下列情況下選擇線性衰減
您的應用程式有自然的邊界、截止期限或臨界值
超過某一點的項目應該完全排除在結果之外
您需要可預測、一致的相關性下降率
使用者應該清楚看到相關項目與不相關項目之間的區別
穩定下降原則
線性衰退會產生直線下降,以固定的速率遞減,直到完全為零。這種模式出現在許多日常情境中,例如倒數計時器、庫存耗盡以及相關性有明確到期點的截止日期臨近。
所有時間參數 (origin,offset,scale) 必須使用與集合資料相同的單位。如果您的收集以不同的單位 (毫秒、微秒) 儲存時間戳記,請相應調整所有參數。
線性衰減
上圖顯示線性衰減如何影響票務平台上的活動清單:
origin(當前日期):當下,相關性達到最大值 (1.0)。offset(1 天):即時事件視窗」- 所有在隔天內發生的事件都會維持完整的相關性評分 (1.0),以確保即將發生的事件不會因為微小的時間差異而受到懲罰。decay(0.5):刻度距離的分數 - 此參數控制相關性的下降速度。scale(10 天):相關性下降到衰減值的時間段 - 距離 10 天的事件,其相關性分數會減半 (0.5)。
從直線曲線可以看出,距離約 16 天以上的事件相關性完全為零,完全不會出現在搜尋結果中。這創造了一個明確的界限,確保使用者只能在定義的時間視窗內看到相關的即將發生的事件。
此行為反映了活動規劃的典型運作方式 - 近期的活動最為相關,未來幾週內的活動重要性遞減,而太遠的未來活動 (或已過去的活動) 則完全不該出現。
計算公式
計算線性遞減分數的數學公式如下:
其中:
以簡單的語言分解:
計算欄位值離原點的距離:
減去偏移量(如果有),但永遠不低於零:
根據您的比例值和衰減值來決定參數s。
從s 減去調整後的距離,再除以s
確保結果永遠不會低於零:0
s 計算將您的比例和衰減參數轉換為分數達到 0 的點。例如,在衰減=0.5 和比例=7 的情況下,分數會在距離=14 (比例值的兩倍) 時正好達到零。
使用線性衰減
線性衰減可以應用在 Milvus 的標準向量搜尋和混合搜尋運算。以下是實現此功能的主要程式碼片段。
在使用衰減函數之前,您必須先建立一個具有適當數值欄位 (如時間戳記、距離等) 的集合,這些欄位將用於衰減計算。如需完整的工作範例,包括集合設定、模式定義和資料插入,請參閱Decay Ranker Tutorial。
建立衰減排名器
在您的資料集中設定了數值欄位 (在本範例中,event_date ,即從現在開始的秒數),請建立一個線性衰減排名器:
時間單位一致性:當使用以時間為基礎的遞減時,請確保origin,scale, 和offset 參數與您的收集資料使用相同的時間單位。如果您的資料集以秒為單位儲存時間戳記,則所有參數都使用秒。如果使用毫秒,則所有參數都使用毫秒。
from pymilvus import Function, FunctionType
import time
# Calculate current time
current_time = int(time.time())
# Create a linear decay ranker for event listings
# Note: All time parameters must use the same unit as your collection data
ranker = Function(
name="event_relevance", # Function identifier
input_field_names=["event_date"], # Numeric field to use
function_type=FunctionType.RERANK, # Function type. Must be RERANK
params={
"reranker": "decay", # Specify decay reranker
"function": "linear", # Choose linear decay
"origin": current_time, # Current time (seconds, matching collection data)
"offset": 12 * 60 * 60, # 12 hour immediate events window (seconds)
"decay": 0.5, # Half score at scale distance
"scale": 7 * 24 * 60 * 60 # 7 days (in seconds, matching collection data)
}
)
import io.milvus.v2.service.vector.request.ranker.DecayRanker;
DecayRanker ranker = DecayRanker.builder()
.name("event_relevance")
.inputFieldNames(Collections.singletonList("event_date"))
.function("linear")
.origin(System.currentTimeMillis())
.offset(12 * 60 * 60)
.decay(0.5)
.scale(7 * 24 * 60 * 60)
.build();
import { FunctionType } from "@zilliz/milvus2-sdk-node";
const ranker = {
name: "event_relevance",
input_field_names: ["event_date"],
type: FunctionType.RERANK,
params: {
reranker: "decay",
function: "linear",
origin: new Date(2025, 1, 15).getTime(),
offset: 12 * 60 * 60,
decay: 0.5,
scale: 7 * 24 * 60 * 60,
},
};
// go
# restful
應用於標準向量搜尋
定義衰減排位器之後,您可以將它傳給ranker 參數,在搜尋作業時套用它:
# Apply decay ranker to vector search
result = milvus_client.search(
collection_name,
data=[your_query_vector], # Replace with your query vector
anns_field="dense", # Vector field to search
limit=10, # Number of results
output_fields=["title", "venue", "event_date"], # Fields to return
ranker=ranker, # Apply the decay ranker
consistency_level="Strong"
)
import io.milvus.v2.common.ConsistencyLevel;
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.response.SearchResp;
import io.milvus.v2.service.vector.request.data.FloatVec;
SearchReq searchReq = SearchReq.builder()
.collectionName(COLLECTION_NAME)
.data(Collections.singletonList(new FloatVec(embedding)))
.annsField("dense")
.limit(10)
.outputFields(Arrays.asList("title", "venue", "event_date"))
.functionScore(FunctionScore.builder()
.addFunction(ranker)
.build())
.consistencyLevel(ConsistencyLevel.STRONG)
.build();
SearchResp searchResp = client.search(searchReq);
const result = await milvusClient.search({
collection_name: "collection_name",
data: [your_query_vector], // Replace with your query vector
anns_field: "dense",
limit: 10,
output_fields: ["title", "venue", "event_date"],
rerank: ranker,
consistency_level: "Strong",
});
// go
# restful