Numpy: BUG: a saída numpy.percentile não é classificada

Criado em 12 out. 2019  ·  16Comentários  ·  Fonte: numpy/numpy

A saída de numpy.percentile nem sempre é classificada

Reproduzindo exemplo de código:

import numpy as np
q = np.arange(0, 1, 0.01) * 100
percentile = np.percentile(np.array([0, 1, 1, 2, 2, 3, 3 , 4, 5, 5, 1, 1, 9, 9 ,9, 8, 8, 7]) * 0.1, q)
equals_sorted = np.sort(percentile) == percentile
print(equals_sorted)
assert equals_sorted.all()

Mensagem de erro:

[Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro
Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro
Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro
Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro
Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro
Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro
Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro
Verdadeiro Verdadeiro Verdadeiro Verdadeiro Verdadeiro Falso Falso Verdadeiro Verdadeiro Verdadeiro Verdadeiro Falso
Verdadeiro Verdadeiro Verdadeiro Falso]
AssertionError Traceback (última chamada mais recente)
dentro
1 q = np.percentil (np.array ([0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 1, 1, 9, 9, 9, 8, 8, 7]) * 0,1, faixa np (0, 1, 0,01) * 100)
2 equals_sorted = np.sort (q) == q
----> 3 assert equals_sorted.all ()

AssertionError:

Informações sobre a versão Numpy / Python:

1.17.2 3.6.8 (v3.6.8: 3c6b436a57, 24 de dezembro de 2018, 02:04:31)
[GCC 4.2.1 compatível com Apple LLVM 6.0 (clang-600.0.57)]

00 - Bug numpy.lib good first issue

Comentários muito úteis

Ei, parece ter havido uma atualização para uma das respostas stackexchange fornecidas por @ eric-wieser com uma boa interpolação alternativa.
O thread inclui uma prova de monotonicidade e a correção proposta parece resolver todos os problemas mencionados.
Se isso fizesse sentido para o problema, eu estaria disposto a implementar isso como um primeiro commit, ou outra pessoa poderia tentar.
20191209_020250

Todos 16 comentários

Por que você espera que seja classificado? O percentil é elemento a elemento - as saídas estão na ordem das entradas.

Oi !
Na verdade, o percentil é o elemento-sábio - ao considerar q , que em nosso caso é
np.arange(0, 1, 0.01) * 100 .
Espero que a saída seja classificada porque q está classificado.

Existem alguns erros numéricos em uma única ULP, que diferem para diferentes entradas com o mesmo valor de saída. Duvido que haja algo a ser feito sobre isso.

Um caso de falha ligeiramente reduzido:

In [40]: np.percentile(np.array([0, 1, 1, 2, 2, 3, 3 , 4, 5, 5, 1, 1, 9, 9 ,9, 8, 8, 7]) * 0.1, [89, 90, 95, 96, 98, 99])
Out[40]: array([0.9, 0.9, 0.9, 0.9, 0.9, 0.9])

In [41]: np.diff(_)
Out[41]:
array([-1.11022302e-16,  2.22044605e-16, -1.11022302e-16,  1.11022302e-16,
       -1.11022302e-16])

aqui mostrando não-classificação por meio do diff.

Acho que provavelmente há algo que podemos fazer a respeito. Acho que isso se resume à estabilidade dessas linhas, que realizam uma operação lerp (essencialmente add(v_below*weights_below, v_above*weights_above) ):

https://github.com/numpy/numpy/blob/b9fa88eec62e34e906689408096beb2450830d9a/numpy/lib/function_base.py#L3907 -L3908

https://github.com/numpy/numpy/blob/b9fa88eec62e34e906689408096beb2450830d9a/numpy/lib/function_base.py#L3928 -L3929

https://github.com/numpy/numpy/blob/b9fa88eec62e34e906689408096beb2450830d9a/numpy/lib/function_base.py#L3939 -L3942

Há uma série de compensações a serem feitas ao interpolar linearmente valores de ponto flutuante, mas suspeito que haja uma escolha "correta" aqui, e simplesmente não a fizemos.

Mais algumas informações básicas aqui: https://math.stackexchange.com/questions/907327/accurate-floating-point-linear-interpolation

Sim, concordo, +1 em reorganizar as operações para que sejam estritamente monotônicas (numericamente) Seria bom se também não fosse pior, ou pelo menos quase idêntico em termos de precisão. Tenho certeza de que realmente não precisamos nos preocupar com algumas operações / velocidades extras aqui.

EDIT: Marcado como bom primeiro exemplar. Mas depois disso, esta é provavelmente uma reorganização bastante direta no código python.

Eu estaria interessado em resolver esse problema. Eu estava olhando para alguns dos casos de falha e percebi que todos eles envolviam interpolação linear entre o mesmo número. ou seja, no exemplo de Eric, todos os percentis que ele listou estão localizados entre dois 9s. Portanto eu acho que a interpolação linear entre eles deve ser 9 exatamente correta? corrigir o problema de interpolação linear entre dois números que são iguais parece que resolveria os problemas apresentados neste bug e não causaria um impacto perceptível no desempenho. Se, no entanto, quisermos garantir que a interpolação linear será sempre monotônica, podemos fazer isso, mas exigirá uma função por partes que eu acho que diminuiria o desempenho.

@ ngonzo95 deve haver uma maneira de soletrar a aritmética da interpolação de forma diferente para conseguir isso, ou seja, alterar / reorganizar a fórmula que é usada para o cálculo (de forma que seja matematicamente idêntica, mas garanta numericamente a monotonicidade). Nenhum cálculo por partes deve ser necessário.

Nenhum cálculo por partes deve ser necessário.

Depende de quais são seus requisitos em lerp . Alguns com os quais podemos ou não nos importar:

  • monotônico ( (lerp(a, b, t1) - lerp(a, b, t0)) * (b - a) * (t1 - t0) >= 0 )
  • limitado ( a <= lerp(a, b, t) <= b )
  • simétrico ( lerp(a, b, t) == lerp(b, a, 1-t) )

( 0 <= t <= 1 )

Tudo bem, eu não esperava que remendos fossem necessários, mas acho que não conheço os intrinsecos disso bem o suficiente.

examinando melhor, descobri que a função a + (ba) * t tem a propriedade de ser monotônica (definição mencionada acima) e consistente (lerp (a, a, t) = a). Eu acredito que isso deve ser suficiente para os requisitos de funções. Parece que uma das principais desvantagens dessa função é que lerp (a, b, 1)! = B. No entanto, acho que a maneira como estamos calculando os pesos garante que 0 <= t <1.

Parece que uma das principais desvantagens dessa função é que lerp (a, b, 1)! = B. No entanto, acho que a maneira como estamos calculando os pesos garante que 0 <= t <1.

Observe que infelizmente lerp(a, b. 1-eps) > b) é possível com essa formulação.

Novo no código aberto.
Queria resolver isso como meu primeiro bom problema. Como posso contribuir? Existem pré-requisitos?

Eu estava olhando para alguns dos casos de falha e percebi que todos eles envolviam interpolação linear entre o mesmo número

No scikit-learn, recentemente nos deparamos com este problema: https://github.com/scikit-learn/scikit-learn/issues/15733

Como esperamos que q esteja estritamente aumentando, podemos aplicar np.maximum.accumulate reordenar o array. No entanto, se pudéssemos resolver o problema no NumPy diretamente, isso seria ótimo. Existe algum lugar onde possamos cavar para ter uma boa solução?

@glemaitre : Todas as linhas relevantes em numpy estão vinculadas em meu comentário acima, https://github.com/numpy/numpy/issues/14685#issuecomment -541467915

Ei, parece ter havido uma atualização para uma das respostas stackexchange fornecidas por @ eric-wieser com uma boa interpolação alternativa.
O thread inclui uma prova de monotonicidade e a correção proposta parece resolver todos os problemas mencionados.
Se isso fizesse sentido para o problema, eu estaria disposto a implementar isso como um primeiro commit, ou outra pessoa poderia tentar.
20191209_020250

Observe que há outro problema com lerp em quantile() : os valores inf não são tratados corretamente, consulte # 12282.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

manuels picture manuels  ·  3Comentários

Kreol64 picture Kreol64  ·  3Comentários

keithbriggs picture keithbriggs  ·  3Comentários

qualiaa picture qualiaa  ·  3Comentários

ghost picture ghost  ·  4Comentários