Junções ASOF, regressão OLS e resumidores adicionais



Junções ASOF, regressão OLS e resumidores adicionais

Desde sparklyr.flintum sparklyr extensão para alavancar Pedra funcionalidades de série temporal por meio de sparklyrperiod introduzido em setembro, fizemos uma série de melhorias e enviamos com sucesso sparklyr.flint 0,2 para CRAN.

Nesta postagem do weblog, destacamos os seguintes novos recursos e melhorias do sparklyr.flint 0,2:

ASOF se junta

Para quem não está familiarizado com o termo, as junções ASOF são operações de junção temporal baseadas na correspondência inexata de carimbos de information/hora. Dentro do contexto de Apache Faíscauma operação de junção, em termos gerais, corresponde a registros de dois quadros de dados (vamos chamá-los left e proper) com base em alguns critérios. Uma junção temporal implica correspondência de registros em left e proper com base em carimbos de information e hora e com correspondência inexata de carimbos de information e hora permitida, normalmente é útil juntar-se left e proper ao longo de uma das seguintes direções temporais:

  1. Olhando para trás: se um registro de left tem carimbo de information/hora tentão ele é combinado com aqueles de proper tendo o carimbo de information/hora mais recente menor ou igual a t.
  2. Olhando para o futuro: se um registro de left tem carimbo de information/hora t, então ele é combinado com aqueles de proper tendo o menor carimbo de information/hora maior ou igual a (ou alternativamente, estritamente maior que) t.

No entanto, muitas vezes não é útil considerar dois carimbos de information/hora como “correspondentes” se estiverem muito distantes. Portanto, uma restrição adicional sobre a quantidade máxima de tempo para olhar para trás ou para frente geralmente também faz parte de uma operação de junção ASOF.

Em sparklyr.flint 0.2, todas as funcionalidades de junção ASOF do Flint são acessíveis através do asof_join() método. Por exemplo, dados 2 RDDs de série temporal left e proper:

library(sparklyr)
library(sparklyr.flint)

sc <- spark_connect(grasp = "native")
left <- copy_to(sc, tibble::tibble(t = seq(10), u = seq(10))) %>%
  from_sdf(is_sorted = TRUE, time_unit = "SECONDS", time_column = "t")
proper <- copy_to(sc, tibble::tibble(t = seq(10) + 1, v = seq(10) + 1L)) %>%
  from_sdf(is_sorted = TRUE, time_unit = "SECONDS", time_column = "t")

O seguinte imprime o resultado da correspondência de cada registro de left com os registros mais recentes de proper que estão no máximo 1 segundo atrás.

print(asof_join(left, proper, tol = "1s", route = ">=") %>% to_sdf())

## # Supply: spark> (?? x 3)
##    time                    u     v
##                   
##  1 1970-01-01 00:00:01     1    NA
##  2 1970-01-01 00:00:02     2     2
##  3 1970-01-01 00:00:03     3     3
##  4 1970-01-01 00:00:04     4     4
##  5 1970-01-01 00:00:05     5     5
##  6 1970-01-01 00:00:06     6     6
##  7 1970-01-01 00:00:07     7     7
##  8 1970-01-01 00:00:08     8     8
##  9 1970-01-01 00:00:09     9     9
## 10 1970-01-01 00:00:10    10    10

Considerando que se mudarmos a direção temporal para “<”, então cada registro de left será comparado com qualquer registro(s) de proper que está estritamente no futuro e está no máximo 1 segundo à frente do recorde atual de left:

print(asof_join(left, proper, tol = "1s", route = "<") %>% to_sdf())

## # Supply: spark> (?? x 3)
##    time                    u     v
##                   
##  1 1970-01-01 00:00:01     1     2
##  2 1970-01-01 00:00:02     2     3
##  3 1970-01-01 00:00:03     3     4
##  4 1970-01-01 00:00:04     4     5
##  5 1970-01-01 00:00:05     5     6
##  6 1970-01-01 00:00:06     6     7
##  7 1970-01-01 00:00:07     7     8
##  8 1970-01-01 00:00:08     8     9
##  9 1970-01-01 00:00:09     9    10
## 10 1970-01-01 00:00:10    10    11

Observe que, independentemente da direção temporal selecionada, uma junção externa esquerda sempre é executada (ou seja, todos os valores de carimbo de information/hora e u valores de left de cima sempre estará presente na saída, e o v coluna na saída conterá NA sempre que não há registro de proper que atenda aos critérios de correspondência).

Regressão OLS

Você deve estar se perguntando se a versão desta funcionalidade no Flint é mais ou menos idêntica à lm() em R. Acontece que tem muito mais a oferecer do que lm() faz. Uma regressão OLS em Flint calculará métricas úteis, como Critério de informação Akaike e Critério de informação bayesianoambos úteis para fins de seleção de modelos, e os cálculos de ambos são paralelizados por Flint para utilizar totalmente o poder computacional disponível em um cluster Spark. Além disso, Flint suporta ignorar regressores constantes ou quase constantes, o que se torna útil quando um termo de interceptação é incluído. Para ver por que isso acontece, precisamos examinar brevemente o objetivo da regressão OLS, que é encontrar algum vetor coluna de coeficientes (mathbf{beta}) que minimiza (|mathbf{y} – mathbf{X} mathbf{beta}|^2)onde (mathbf{y}) é o vetor coluna de variáveis ​​de resposta, e (mathbf{X}) é uma matriz que consiste em colunas de regressores mais uma coluna inteira de (1)s representando os termos de interceptação. A solução para este problema é (mathbf{beta} = (mathbf{X}^intercalmathbf{X})^{-1}mathbf{X}^intercalmathbf{y})assumindo a matriz Gram (mathbf{X}^intercalmathbf{X}) não é singular. No entanto, se (mathbf{X}) contém uma coluna de todos (1)s de termos de interceptação, e outra coluna formada por um regressor que é constante (ou quase), então colunas de (mathbf{X}) será linearmente dependente (ou quase) e (mathbf{X}^intercalmathbf{X}) será singular (ou quase), o que apresenta um problema em termos de computação. No entanto, se um regressor for constante, então ele desempenha essencialmente o mesmo papel que os termos de interceptação. Então, simplesmente excluindo esse regressor constante em (mathbf{X}) resolve o problema. Além disso, falando em inverter a matriz de Gram, os leitores que se lembram do conceito de “número de condição” da análise numérica devem estar pensando como a computação (mathbf{beta} = (mathbf{X}^intercalmathbf{X})^{-1}mathbf{X}^intercalmathbf{y}) poderia ser numericamente instável se (mathbf{X}^intercalmathbf{X}) tem um grande número de condição. É por isso que Flint também gera o número de condição da matriz de Gram no resultado da regressão OLS, para que se possa verificar se o problema de minimização quadrática subjacente que está sendo resolvido está bem condicionado.

Portanto, para resumir, a funcionalidade de regressão OLS implementada em Flint não apenas produz a solução para o problema, mas também calcula métricas úteis que ajudam os cientistas de dados a avaliar a sanidade e a qualidade preditiva do modelo resultante.

Para ver a regressão OLS em ação com sparklyr.flintpode-se executar o seguinte exemplo:

mtcars_sdf <- copy_to(sc, mtcars, overwrite = TRUE) %>%
  dplyr::mutate(time = 0L)
mtcars_ts <- from_sdf(mtcars_sdf, is_sorted = TRUE, time_unit = "SECONDS")
mannequin <- ols_regression(mtcars_ts, mpg ~ hp + wt) %>% to_sdf()

print(mannequin %>% dplyr::choose(akaikeIC, bayesIC, cond))

## # Supply: spark> (?? x 3)
##   akaikeIC bayesIC    cond
##            
## 1     155.    159. 345403.

# ^ output says situation variety of the Gram matrix was inside cause

e obter (mathbf{beta})o vetor de coeficientes ótimos, com o seguinte:

print(mannequin %>% dplyr::pull(beta))

## ((1))
## (1) -0.03177295 -3.87783074

Resumidores Adicionais

A EWMA (média móvel ponderada exponencial), a meia-vida da EMA e os resumidores de momentos padronizados (ou seja, assimetria e curtose), juntamente com alguns outros que estavam faltando no sparklyr.flint 0.1 agora são totalmente suportados em sparklyr.flint 0,2.

Melhor integração com sparklyr

Enquanto sparklyr.flint 0,1 incluiu um gather() método para exportar dados de um RDD de série temporal Flint para um quadro de dados R, ele não tinha um método semelhante para extrair o quadro de dados Spark subjacente de um RDD de série temporal Flint. Isto foi claramente um descuido. Em sparklyr.flint 0,2, pode-se ligar to_sdf() em um RDD de série temporal para recuperar um quadro de dados Spark que pode ser usado em sparklyr (por exemplo, como mostrado por mannequin %>% to_sdf() %>% dplyr::choose(...) exemplos acima). Também é possível obter a referência do objeto JVM do quadro de dados Spark subjacente chamando spark_dataframe() em um RDD de série temporal Flint (isso geralmente é desnecessário na grande maioria dos sparklyr casos de uso).

Conclusão

Apresentamos uma série de novos recursos e melhorias introduzidas no sparklyr.flint 0.2 e nos aprofundamos em alguns deles nesta postagem do weblog. Esperamos que você esteja tão entusiasmado com eles quanto nós.

Obrigado por ler!

Reconhecimento

O autor gostaria de agradecer a Mara (@batpigandme), Sigrid (@skeydan) e Javier (@javierluraschi) por suas fantásticas contribuições editoriais nesta postagem do weblog!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *