線性衰減Compatible with Milvus 2.6.x

線性衰減 (Linear Decay) 在您的搜尋結果中創造了一個以絕對零點為終點的直線下降。就像即將發生的事件倒數一樣,相關性逐漸減弱,直到事件結束,線性衰減在項目離開您的理想點時,應用可預測的、穩定的相關性減弱,直到它們完全消失。當您想要一致的衰減率且有明確的分界線時,這種方法是最理想的選擇,可確保超出某個邊界的項目完全被排除在結果之外。

與其他衰減函數不同:

  • 高斯衰減遵循逐漸接近但永遠不會達到零的鐘形曲線

  • 指數衰減保持一個長尾,其相關性極低,並且無限延伸

線性衰減獨一無二地創建了一個明確的終點,因此對於有自然邊界或截止日期的應用程式特別有效。

何時使用線性衰減

線性衰減對以下情況特別有效

使用個案

範例

為什麼線性效果好

活動列表

音樂會門票平台

為太遠的活動建立明確的截止日期

限時優惠

快銷、促銷

確保不會出現過期或即將過期的優惠

送貨半徑

送餐、快遞服務

強制執行硬性地理界限

限制年齡的內容

約會平台、媒體服務

建立確定的年齡門檻

在下列情況下選擇線性衰減

  • 您的應用程式有自然的邊界、截止期限或臨界值

  • 超過某一點的項目應該完全排除在結果之外

  • 您需要可預測、一致的相關性下降率

  • 使用者應該清楚看到相關項目與不相關項目之間的區別

穩定下降原則

線性衰退會產生直線下降,以固定的速率遞減,直到完全為零。這種模式出現在許多日常情境中,例如倒數計時器、庫存耗盡以及相關性有明確到期點的截止日期臨近。

所有時間參數 (origin,offset,scale) 必須使用與集合資料相同的單位。如果您的收集以不同的單位 (毫秒、微秒) 儲存時間戳記,請相應調整所有參數。

Linear Decay 線性衰減

上圖顯示線性衰減如何影響票務平台上的活動清單:

  • origin (當前日期):當下,相關性達到最大值 (1.0)。

  • offset (1 天):即時事件視窗」- 所有在隔天內發生的事件都會維持完整的相關性評分 (1.0),以確保即將發生的事件不會因為微小的時間差異而受到懲罰。

  • decay (0.5):刻度距離的分數 - 此參數控制相關性的下降速度。

  • scale (10 天):相關性下降到衰減值的時間段 - 距離 10 天的事件,其相關性分數會減半 (0.5)。

從直線曲線可以看出,距離約 16 天以上的事件相關性完全為零,完全不會出現在搜尋結果中。這創造了一個明確的界限,確保使用者只能在定義的時間視窗內看到相關的即將發生的事件。

此行為反映了活動規劃的典型運作方式 - 近期的活動最為相關,未來幾週內的活動重要性遞減,而太遠的未來活動 (或已過去的活動) 則完全不該出現。

計算公式

計算線性遞減分數的數學公式如下:

S(doc)=max(smax(0,fieldvaluedocoriginoffset)s,0)S(doc) = \max\left( \frac{s - \max(0, |fieldvalue_{doc} - origin| - offset)}{s}, 0 \right)

其中:

s=scale(1.0decay)s = \frac{scale}{(1.0 - decay)}

以簡單的語言分解:

  1. 計算欄位值離原點的距離:∣fieldvaluedoc-origin∣|fieldvalue_{doc} - origin|

  2. 減去偏移量(如果有),但永遠不低於零:max(0,distance-offset)\max(0, distance - offset)

  3. 根據您的比例值和衰減值來決定參數sss。

  4. sss 減去調整後的距離,再除以sss

  5. 確保結果永遠不會低於零:max(result,0)\max(result, 0)0

sss 計算將您的比例和衰減參數轉換為分數達到 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

免費嘗試托管的 Milvus

Zilliz Cloud 無縫接入,由 Milvus 提供動力,速度提升 10 倍。

開始使用
反饋

這個頁面有幫助嗎?