Avaliação lenta de série temporal

A avaliação preguiçosa é uma estratégia de avaliação que atrasa a avaliação de uma expressão até que seu valor seja necessário. Quando combinada com memorização, a estratégia de avaliação preguiçosa evita avaliações repetidas e pode reduzir o tempo de execução de determinadas funções por um fator significativo.

A biblioteca da série temporal usa avaliação preguiçosa para processar dados. Teoricamente, um gráfico de execução é construído sobre dados de séries temporais cuja avaliação é acionada somente quando sua saída é materializada. Supondo que um objeto esteja se movendo em um espaço dimensional cujo local é capturado por x(t). É possível determinar a aceleração/frenagem rigorosa brusca (h(t)) deste objeto usando as séries temporais de velocidade (v(t)) e aceleração (a(t)) da seguinte forma:

# 1d location timeseries
x(t) = input location timeseries

# velocity - first derivative of x(t)
v(t) = x(t) - x(t-1)

# acceleration - second derivative of x(t)
a(t) = v(t) - v(t-1)

# harsh acceleration/braking using thresholds on acceleration
h(t) = +1 if a(t) > threshold_acceleration
     = -1 if a(t) < threshold_deceleration
     = 0 otherwise

Isso resulta em um gráfico de execução simples no formato:

x(t) --> v(t) --> a(t) --> h(t)

As avaliações são acionadas apenas quando uma ação é executada, como compute h(5...10), ou seja, compute h(5), ..., h(10). A biblioteca captura dependências temporais limitadas entre séries temporais. Neste exemplo, h(5...10) requer a(5...10), que, por sua vez, requer v(4...10), que requer x(3...10). Somente as partes relevantes de a(t), v(t) e x(t) são avaliadas.

h(5...10) <-- a(5...10) <-- v(4...10) <-- x(3...10)

Além disso, as avaliações são memorizadas e podem ser reutilizadas em ações subsequentes no h. Por exemplo, quando uma solicitação para h(7...12) segue uma solicitação para h(5...10), os valores memorizados h(7...10) são alavancados; além disso, h(11...12) seria avaliado usando a(11...12), v(10...12) e x(9...12) que, por sua vez, alavancaria v(10) e x(9...10) memorizados do cálculo anterior.

Em um exemplo mais geral, você poderia definir uma série temporal de velocidade suavizada da seguinte forma:

# 1d location timeseries
x(t) = input location timeseries

# velocity - first derivative of x(t)
v(t) = x(t) - x(t-1)

# smoothened velocity
# alpha is the smoothing factor
# n is a smoothing history
v_smooth(t) =  (v(t)*1.0 + v(t-1)*alpha + ... + v(t-n)*alpha^n) / (1 + alpha + ... + alpha^n)

# acceleration - second derivative of x(t)
a(t) = v_smooth(t) - v_smooth(t-1)

Neste exemplo h(l...u) tem a dependência temporal a seguir. A avaliação de h(l...u) aderiria estritamente a essa dependência temporal com a memorização.

h(l...u) <-- a(l...u) <-- v_smooth(l-1...u) <-- v(l-n-1...u) <-- x(l-n-2...u)

Um exemplo

O exemplo a seguir mostra um trecho de código python que implementa a aceleração brusca em uma série temporal de memória simples. A biblioteca inclui várias transformações integradas. Neste exemplo, a transformação de diferença é aplicada duas vezes à série temporal de localização para calcular séries temporais de aceleração. Uma operação de mapa é aplicada à série temporal de aceleração usando uma função lambda brusca, que é definida após a amostra de código, que mapeia a aceleração para +1 (aceleração brusca), -1 (frenagem brusca) e 0 (caso contrário). A operação de filtro seleciona apenas as instâncias em que a aceleração ou a frenagem brusca é observada. Antes de chamar get_values, um gráfico de execução é criado, mas nenhum cálculo é realizado. Na chamada para get_values(5, 10), a avaliação é executada com memorização na dependência temporal mais limitada possível no gráfico de execução.

import tspy
from tspy.builders.functions import transformers

x = tspy.time_series([1.0, 2.0, 4.0, 7.0, 11.0, 16.0, 22.0, 29.0, 28.0, 30.0, 29.0, 30.0, 30.0])
v = x.transform(transformers.difference())
a = v.transform(transformers.difference())
h = a.map(harsh).filter(lambda h: h != 0)

print(h[5, 10])

O lambda brusco é definido da seguinte forma:

def harsh(a):
    threshold_acceleration = 2.0
    threshold_braking = -2.0

    if (a > threshold_acceleration):
        return +1
    elif (a < threshold_braking):
        return -1
    else:
        return 0

Saiba Mais

Para usar o tspy Python SDK, consulte a Documentação do tspy Python SDK.