半时间衰减封装函数
[代码]
作者:lh
import math
from typing import Optional
def half_life_decay(
delta_days: float,
half_life_days: float,
*,
cap_days: Optional[float] = None,
min_score: float = 0.0,
max_score: float = 1.0,
) -> float:
"""
半衰期时间衰减函数(更适合做用户画像/兴趣权重)。
核心公式:
score = 0.5 ** (delta_days / half_life_days)
含义:
- half_life_days(半衰期)= 过这么多天,权重衰减到原来的 1/2
- delta_days = 距离行为发生过去了多少天
- score 越接近 1,代表越“新”的行为影响越大;越接近 0 代表越“旧”的行为影响越小
参数:
delta_days: 距离事件发生的天数(>=0,允许 float;例如 0.5 表示半天)
half_life_days: 半衰期天数(>0),例如 30 表示每过 30 天影响减半
cap_days: 可选,硬截断阈值;如果 delta_days > cap_days,则直接返回 min_score(表示太久远不计)
min_score: 最小权重下限(例如 0.0 或 0.001),用于防止极老事件产生“完全为 0”或保留极小影响
max_score: 最大权重上限(通常 1.0),用于保护值域
返回:
float:最终衰减权重(会被 clamp 到 [min_score, max_score])
"""
# 半衰期必须大于 0,否则公式无意义(会除以 0)
if half_life_days <= 0:
raise ValueError("half_life_days must be > 0")
# 处理异常 delta_days:
# - None 或 NaN:直接返回最小权重(认为不可用/缺失)
if delta_days is None or math.isnan(delta_days):
return min_score
# delta_days 不应为负数;如果出现(例如时间差算错),就按 0 天处理(最新)
if delta_days < 0:
delta_days = 0.0
# 可选:硬截断
# 如果你想只看近 90 天画像,那么 90 天前的行为直接不计
if cap_days is not None and delta_days > cap_days:
return min_score
# 半衰期衰减核心:
# delta_days=0 -> score=1
# delta_days=half_life_days -> score=0.5
# delta_days=2*half_life_days -> score=0.25
score = 0.5 ** (delta_days / half_life_days)
# clamp(钳制):把 score 限制在 [min_score, max_score] 范围内,避免异常值
if score < min_score:
score = min_score
if score > max_score:
score = max_score
return float(score)
def half_life_to_lambda(half_life_days: float) -> float:
"""
将“半衰期 half_life_days”转换为“指数衰减 lambda”。
指数衰减公式:
score = exp(-lambda * delta_days)
半衰期与 lambda 的关系:
当 delta_days = half_life_days 时,score = 0.5
=> 0.5 = exp(-lambda * half_life_days)
=> lambda = ln(2) / half_life_days
"""
if half_life_days <= 0:
raise ValueError("half_life_days must be > 0")
return math.log(2.0) / half_life_days
def lambda_to_half_life(lambda_decay: float) -> float:
"""
将“指数衰减 lambda”转换为“半衰期 half_life_days”。
由:
lambda = ln(2) / half_life
得:
half_life = ln(2) / lambda
"""
if lambda_decay <= 0:
raise ValueError("lambda_decay must be > 0")
return math.log(2.0) / lambda_decay
import math
from typing import Optional
def half_life_decay(
delta_days: float,
half_life_days: float,
*,
cap_days: Optional[float] = None,
min_score: float = 0.0,
max_score: float = 1.0,
) -> float:
"""
半衰期时间衰减函数(更适合做用户画像/兴趣权重)。
核心公式:
score = 0.5 ** (delta_days / half_life_days)
含义:
- half_life_days(半衰期)= 过这么多天,权重衰减到原来的 1/2
- delta_days = 距离行为发生过去了多少天
- score 越接近 1,代表越“新”的行为影响越大;越接近 0 代表越“旧”的行为影响越小
参数:
delta_days: 距离事件发生的天数(>=0,允许 float;例如 0.5 表示半天)
half_life_days: 半衰期天数(>0),例如 30 表示每过 30 天影响减半
cap_days: 可选,硬截断阈值;如果 delta_days > cap_days,则直接返回 min_score(表示太久远不计)
min_score: 最小权重下限(例如 0.0 或 0.001),用于防止极老事件产生“完全为 0”或保留极小影响
max_score: 最大权重上限(通常 1.0),用于保护值域
返回:
float:最终衰减权重(会被 clamp 到 [min_score, max_score])
"""
# 半衰期必须大于 0,否则公式无意义(会除以 0)
if half_life_days <= 0:
raise ValueError("half_life_days must be > 0")
# 处理异常 delta_days:
# - None 或 NaN:直接返回最小权重(认为不可用/缺失)
if delta_days is None or math.isnan(delta_days):
return min_score
# delta_days 不应为负数;如果出现(例如时间差算错),就按 0 天处理(最新)
if delta_days < 0:
delta_days = 0.0
# 可选:硬截断
# 如果你想只看近 90 天画像,那么 90 天前的行为直接不计
if cap_days is not None and delta_days > cap_days:
return min_score
# 半衰期衰减核心:
# delta_days=0 -> score=1
# delta_days=half_life_days -> score=0.5
# delta_days=2*half_life_days -> score=0.25
score = 0.5 ** (delta_days / half_life_days)
# clamp(钳制):把 score 限制在 [min_score, max_score] 范围内,避免异常值
if score < min_score:
score = min_score
if score > max_score:
score = max_score
return float(score)
def half_life_to_lambda(half_life_days: float) -> float:
"""
将“半衰期 half_life_days”转换为“指数衰减 lambda”。
指数衰减公式:
score = exp(-lambda * delta_days)
半衰期与 lambda 的关系:
当 delta_days = half_life_days 时,score = 0.5
=> 0.5 = exp(-lambda * half_life_days)
=> lambda = ln(2) / half_life_days
"""
if half_life_days <= 0:
raise ValueError("half_life_days must be > 0")
return math.log(2.0) / half_life_days
def lambda_to_half_life(lambda_decay: float) -> float:
"""
将“指数衰减 lambda”转换为“半衰期 half_life_days”。
由:
lambda = ln(2) / half_life
得:
half_life = ln(2) / lambda
"""
if lambda_decay <= 0:
raise ValueError("lambda_decay must be > 0")
return math.log(2.0) / lambda_decay