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

时间:2011-10-04 17:20:01

标签: 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)))))

1 个答案:

答案 0 :(得分:5)

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

T_no_events(dt) = T_min + (T_0 - T_min)*exp(- dt / t_cooling)

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

T_post_event = T_pre_event + (T_max - T_pre_event) / num_events_to_heat

一些注意事项:

  • t_cooling是让事情冷却的时间1/e = 1/(2.718...)

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

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

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

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