使用牛顿冷却的clojure中的新近度图

Ben*_*ert 14 algorithm math clojure

我正在Clojure中构建一个系统,它实时消耗事件并根据最近收到的类似消息对其进行操作.我想使用基于牛顿冷却的新近度分数来实现这一点.

换句话说,当一个事件到来时,我希望能够给它分配到1.0之间的得分(之前从来没有发生过,或在牛顿方程"环境温度")和10.0(烫烫烫的,已经发生多次在过去一分钟).

我有什么这个数据结构看起来像一个模糊的概念 - 每一个"事件类型"是地图键,每一个地图的值应该包含一些设置时间戳以前的事件,也许目前的"热"的应该是一个平均运行事件类型,但我无法弄清楚如何开始实现.具体来说,我无法弄清楚如何从牛顿的实际方程出发,这是非常通用的,并将其应用于这个特定的场景.

有没有人有任何指针?有人会建议一个更简单的"新近度分数算法"让我开始,这可以被牛顿冷却下来取代吗?

编辑:这是一些clojure代码!它将事件称为字母,但显然可以重新用于处理任何其他类型的对象.

(ns heater.core
    (:require [clojure.contrib.generic.math-functions :as math]))

(def letter-recency-map (ref {}))

(def MIN-TEMP 1.0)
(def MAX-TEMP 10.0)
;; Cooling time is 15 seconds
(def COOLING-TIME 15000)
;; Events required to reach max heat
(def EVENTS-TO-HEAT 5.0)

(defn temp-since [t since now]
    (+
        MIN-TEMP
        (*
            (math/exp (/
                (- (- now since))
                COOLING-TIME))
            (- t MIN-TEMP))))

(defn temp-post-event [temp-pre-event]
    (+ temp-pre-event
        (/
            (- MAX-TEMP temp-pre-event)
            EVENTS-TO-HEAT)))

(defn get-letter-heat [letter]
        (dosync
            (let [heat-record (get (ensure letter-recency-map) letter)]
            (if (= heat-record nil)
                (do
                (alter letter-recency-map conj {letter {:time (System/currentTimeMillis) :heat 1.0}})
                MIN-TEMP)
                (let [now (System/currentTimeMillis)
                     new-temp-cooled (temp-since (:heat heat-record) (:time heat-record) now)
                     new-temp-event (temp-post-event new-temp-cooled)]
                     (alter letter-recency-map conj {letter {:time now :heat new-temp-event}})
                    new-temp-event)))))
Run Code Online (Sandbox Code Playgroud)

com*_*orm 5

在没有任何事件的情况下,冷却方程的解是指数衰减.假设T_0是冷却期开始时的温度,并且dt是时间步长(根据系统时间或其他因素计算),因为您评估温度为T_0:

T_no_events(dt) = T_min + (T_0 - T_min)*exp(- dt / t_cooling)
Run Code Online (Sandbox Code Playgroud)

由于您的事件是离散的冲动,并且您具有最高温度,因此您希望每个事件具有给定的比率:

T_post_event = T_pre_event + (T_max - T_pre_event) / num_events_to_heat
Run Code Online (Sandbox Code Playgroud)

一些说明:

  • t_cooling是时候冷静下来的时间了1/e = 1/(2.718...).

  • num_events_to_heat是具有可比效果所需的事件数量T_max.它应该是一个中等大的正值(说5.0或更多?).请注意,如果num_events_to_heat==1.0每个事件都将温度重置为T_max,这不是很有趣,因此该值应该至少大于1.

  • 从理论上讲,加热和冷却都不应该分别达到最高和最低温度(假设参数设置如上,并且你从两者之间的某处开始).但在实践中,过程的指数性质应该足够接近,因为没有区别......

  • 要实现此功能,您只需存储上次更新的时间戳和温度.收到活动时,请执行冷却步骤,然后执行加热事件,并使用新的温度和时间戳进行更新.

  • 请注意,只读查询不需要更新:您可以计算自上次更新以来的冷却.