지수 감쇠Compatible with Milvus 2.6.x
지수 감쇠는 검색 결과에서 가파른 초기 하락과 긴 꼬리를 생성합니다. 처음에는 관련성이 급격히 감소하지만 시간이 지나면서 일부 기사의 중요성이 유지되는 속보 사이클처럼, 지수 감쇠는 이상적인 범위를 벗어난 항목에 급격한 페널티를 적용하는 동시에 멀리 떨어진 항목은 계속 검색할 수 있도록 합니다. 이 접근 방식은 근접성이나 최신성에 높은 우선순위를 부여하고 싶지만 먼 거리에 있는 옵션을 완전히 없애고 싶지 않을 때 이상적입니다.
다른 감쇠 함수와 달리
가우스 감쇠는 보다 점진적인 종 모양의 감쇠를 생성합니다.
선형 감쇠는 정확히 0에 도달할 때까지 일정한 비율로 감소합니다.
지수 감쇠는 고유하게 페널티를 '프론트로드'하여 관련성 감소의 대부분을 조기에 적용하는 동시에 관련성을 최소화하지만 0이 아닌 긴 꼬리를 유지합니다.
지수 감쇠를 사용하는 경우
지수 감쇠는 특히 다음과 같은 경우에 효과적입니다:
사용 사례 |
예시 |
지수 감쇠가 잘 작동하는 이유 |
|---|---|---|
뉴스 피드 |
뉴스 포털 속보 |
며칠 전의 중요한 뉴스를 계속 표시하면서 오래된 뉴스의 관련성을 빠르게 줄입니다. |
소셜 미디어 타임라인 |
활동 피드, 상태 업데이트 |
새로운 콘텐츠를 강조하되 입소문이 난 오래된 콘텐츠는 노출되도록 합니다. |
알림 시스템 |
알림 우선순위 지정 |
중요한 알림에 대한 가시성을 유지하면서 최근 알림에 긴급성을 부여합니다. |
플래시 세일 |
기간 한정 행사 |
마감일이 다가올수록 가시성을 빠르게 감소시킵니다. |
기하급수적 감쇠 시점을 선택하세요:
사용자가 매우 최근 또는 가까운 품목이 결과를 강력하게 지배할 것으로 기대하는 경우
예외적으로 관련성이 높은 경우 오래되거나 더 먼 항목도 여전히 검색될 수 있어야 합니다.
연관성 감쇠는 전면적으로 이루어져야 합니다(처음에는 가파르게, 나중에는 점진적으로).
급격한 드롭오프 원칙
지수적 감쇠는 처음에는 빠르게 하락하다가 점차 평평해져 0에 가까워지지만 결코 0에 도달하지 않는 긴 꼬리 모양의 곡선을 만듭니다. 이 수학적 패턴은 방사능 붕괴, 인구 감소, 시간에 따른 정보 관련성과 같은 자연 현상에서 자주 나타납니다.
모든 시간 매개변수(origin, offset, scale)는 수집 데이터와 동일한 단위를 사용해야 합니다. 컬렉션에서 타임스탬프를 다른 단위(밀리초, 마이크로초)로 저장하는 경우 모든 매개변수를 그에 맞게 조정하세요.
지수 붕괴
위의 그래프는 디지털 뉴스 플랫폼에서 지수 감쇠가 뉴스 기사 순위에 어떤 영향을 미치는지 보여줍니다:
origin(현재 시간): 관련성이 최대(1.0)인 현재 시점입니다.offset(3시간): 지난 3시간 이내에 게시된 모든 기사의 관련성 점수가 최대(1.0)로 유지되는 '속보 창'으로, 아주 최근의 뉴스가 사소한 시간 차이로 인해 불필요하게 불이익을 받지 않도록 합니다.decay(0.5): 스케일 거리의 점수 - 이 매개변수는 시간이 지남에 따라 점수가 얼마나 급격하게 감소하는지를 제어합니다.scale(24시간): 관련성이 감쇠 값으로 떨어지는 시간 - 정확히 24시간이 지난 뉴스 기사는 관련성 점수가 절반(0.5)으로 떨어집니다.
곡선에서 볼 수 있듯이 24시간이 지난 뉴스 기사는 관련성이 계속 감소하지만 0에 도달하지는 않습니다. 며칠 전의 기사라도 최소한의 관련성은 유지되므로 중요하지만 오래된 뉴스는 순위는 낮지만 여전히 피드에 표시될 수 있습니다.
이 동작은 뉴스 관련성이 일반적으로 작동하는 방식을 모방한 것으로, 아주 최근의 기사가 강력하게 지배적이지만 사용자의 관심사와 매우 관련이 있는 경우 중요한 오래된 기사가 여전히 돌파할 수 있습니다.
공식
지수 붕괴 점수를 계산하는 수학 공식은 다음과 같습니다:
Where:
이를 쉬운 언어로 분석하면 다음과 같습니다:
필드 값이 원점으로부터 얼마나 멀리 떨어져 있는지 계산합니다:
오프셋(있는 경우)을 빼되 0 이하로 내려가지 않도록 합니다: .
스케일과 감쇠 매개변수에서 계산한 곱합니다.
지수를 구하면 0과 1 사이의 값을 얻을 수 있습니다: .
계산은 스케일 및 감쇠 매개변수를 지수 함수의 비율 매개변수로 변환합니다. 음수일수록 초기 하락이 더 가파르게 나타납니다.
지수 감쇠 사용
지수 감쇠는 Milvus의 표준 벡터 검색과 하이브리드 검색 연산 모두에 적용할 수 있습니다. 다음은 이 기능을 구현하기 위한 주요 코드 스니펫입니다.
감쇠 함수를 사용하기 전에 먼저 감쇠 계산에 사용할 적절한 숫자 필드(타임스탬프, 거리 등)가 있는 컬렉션을 만들어야 합니다. 컬렉션 설정, 스키마 정의, 데이터 삽입을 포함한 전체 작업 예제는 감쇠 순위 자습서를 참조하세요.
감쇠 랭커 생성하기
숫자 필드(이 예에서는 publish_time)로 컬렉션을 설정한 후 지수 감쇠 순위자를 만듭니다:
시간 단위 일관성: 시간 기반 감쇠를 사용하는 경우 origin, scale, offset 매개변수가 컬렉션 데이터와 동일한 시간 단위를 사용하는지 확인하세요. 컬렉션에서 타임스탬프를 초 단위로 저장하는 경우 모든 매개변수에 초를 사용합니다. 밀리초를 사용하는 경우 모든 매개변수에 밀리초를 사용합니다.
from pymilvus import Function, FunctionType
import datetime
# Create an exponential decay ranker for news recency
# Note: All time parameters must use the same unit as your collection data
ranker = Function(
name="news_recency", # Function identifier
input_field_names=["publish_time"], # Numeric field to use
function_type=FunctionType.RERANK, # Function type. Must be RERANK
params={
"reranker": "decay", # Specify decay reranker
"function": "exp", # Choose exponential decay
"origin": int(datetime.datetime.now().timestamp()), # Current time (seconds, matching collection data)
"offset": 3 * 60 * 60, # 3 hour breaking news window (seconds)
"decay": 0.5, # Half score at scale distance
"scale": 24 * 60 * 60 # 24 hours (in seconds, matching collection data)
}
)
import io.milvus.v2.service.vector.request.ranker.DecayRanker;
DecayRanker ranker = DecayRanker.builder()
.name("news_recency")
.inputFieldNames(Collections.singletonList("publish_time"))
.function("exp")
.origin(System.currentTimeMillis())
.offset(3 * 60 * 60)
.decay(0.5)
.scale(24 * 60 * 60)
.build();
import { FunctionType } from "@zilliz/milvus2-sdk-node";
const ranker = {
name: "news_recency",
input_field_names: ["publish_time"],
type: FunctionType.RERANK,
params: {
reranker: "decay",
function: "exp",
origin: new Date(2025, 1, 15).getTime(),
offset: 3 * 60 * 60,
decay: 0.5,
scale: 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", "publish_time"], # 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.EmbeddedText;
SearchReq searchReq = SearchReq.builder()
.collectionName(COLLECTION_NAME)
.data(Collections.singletonList(new EmbeddedText("market analysis")))
.annsField("vector_field")
.limit(10)
.outputFields(Arrays.asList("title", "publish_time"))
.functionScore(FunctionScore.builder()
.addFunction(ranker)
.build())
.consistencyLevel(ConsistencyLevel.STRONG)
.build();
SearchResp searchResp = client.search(searchReq);
import { FunctionType MilvusClient } from "@zilliz/milvus2-sdk-node";
const milvusClient = new MilvusClient("http://localhost:19530");
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", "publish_time"],
rerank: ranker,
consistency_level: "Strong",
});
// go
# restful