Numpy: Suporte à coerção de matriz de pato

Criado em 25 jun. 2019  ·  55Comentários  ·  Fonte: numpy/numpy

Abrindo este problema após alguma discussão com @shoyer , @pentschev e @mrocklin em questão (https://github.com/dask/dask/issues/4883). AIUI isso foi discutido no NEP 22 (portanto, estou repetindo principalmente as idéias de outras pessoas aqui para renovar a discussão e corrigir meu próprio mal-entendido;).

Seria útil para várias bibliotecas de array downstream terem uma função para garantir que temos algum array duck (como ndarray ). Isso seria algo semelhante a np.asanyarray , mas sem a necessidade de subclasses. Isso permitiria que as bibliotecas retornassem seu próprio tipo de array (pato) . Se nenhuma conversão adequada fosse suportada pelo objeto, poderíamos recorrer a ndarray subclasses, ndarray s e coerção de outras coisas (listas aninhadas) para ndarray s.

cc @njsmith (co-autor do NEP 22)

01 - Enhancement numpy.core

Comentários muito úteis

Talvez quack_array :)

Todos 55 comentários

A implementação proposta seria semelhante a esta:

import numpy as np

# hypothetical np.duckarray() function
def duckarray(array_like):
  if hasattr(array_like, '__duckarray__'):
    # return an object that can be substituted for np.ndarray
    return array_like.__duckarray__()
  return np.asarray(array_like)

Exemplo de uso:

class SparseArray:
  def __duckarray__(self):
    return self
  def __array__(self):
    raise TypeError

np.duckarray(SparseArray())  # returns a SparseArray object
np.array(SparseArray())  # raises TypeError

Aqui, usei np.duckarray e __duckarray__ como marcadores de posição, mas provavelmente podemos fazer melhor com esses nomes. Veja a Terminologia da NEP 22:

“Duck array” funciona bem como um marcador por enquanto, mas é bastante jargão e pode confundir os novos usuários, então podemos escolher outra coisa para as funções reais da API. Infelizmente, "semelhante a array" já é considerado o conceito de "qualquer coisa que pode ser coagido em um array" (incluindo, por exemplo, objetos de lista), e "anyarray" já é considerado o conceito de "algo que compartilha a implementação de ndarray, mas tem semântica diferente ”, que é o oposto de um array de pato (por exemplo, np.matrix é um“ anyarray ”, mas não é um“ array de pato ”). Este é um galpão de bicicletas clássico, então, por enquanto, estamos usando apenas “duck array”. Algumas opções possíveis incluem: arrayish, pseudoarray, nominalarray, ersatzarray, arraymimic, ...

Algumas outras idéias de nomes: np.array_compatible() , np.array_api() ....

np.array_compatible poderia funcionar, embora eu não tenha certeza se gosto mais dele do que duckarray . np.array_api não gosto, dá a ideia errada imho.

Como depois de muito tempo não encontramos um nome melhor, talvez devêssemos abençoar o nome "duck-array" ......

Eu gosto da palavra compatível, talvez possamos pensar em variações ao longo dessa linha também as_compatible_array (de alguma forma implica que todos os objetos compatíveis são matrizes). O as talvez seja irritante (parcialmente porque todas as funções as não têm espaços). "duck" parece bom em bibliotecas, mas acho um pouco estranho para pessoas aleatórias vendo isso. Portanto, acho que não gosto de "pato" se e somente se quisermos que os usuários downstream o usem muito (ou seja, mesmo quando eu começo a escrever uma pequena ferramenta para mim / um pequeno laboratório).

Talvez quack_array :)

Para estender um pouco o assunto, há um outro caso que não é abordado com np.duckarray , que é a criação de novos arrays com um tipo baseado em um tipo existente, semelhante a funções como np.empty_like do. Atualmente, podemos fazer coisas assim:

>>> import numpy as np, cupy as cp
>>> a  = cp.array([1, 2])
>>> b = np.ones_like(a)
>>> type(b)
<class 'cupy.core.core.ndarray'>

Por outro lado, se tivermos um array_like qual gostaríamos de criar um array CuPy através da API do NumPy, isso não é possível. Acho que seria útil ter algo como:

import numpy as np, cupy as cp
a  = cp.array([1, 2])
b = [1, 2]
c = np.asarray(b, like=a)

Alguma ideia / sugestão sobre isso?

Talvez np.copy_like? Gostaríamos de definir cuidadosamente quais propriedades
(por exemplo, incluindo dtype ou não) são copiados do outro array.

Na segunda-feira, 1º de julho de 2019 às 5:40 Peter Andreas Entschev <
notificaçõ[email protected]> escreveu:

Para estender um pouco o assunto, há um outro caso que não foi abordado
com np.duckarray, que é a criação de novos arrays com um tipo baseado
em um tipo existente, semelhante ao que funções como np.empty_like fazem.
Atualmente, podemos fazer coisas assim:

import numpy como np, cupy como cp >>> a = cp.array ([1, 2]) >>> b = np.ones_like (a) >>> type (b)

Por outro lado, se temos um array_like que gostaríamos de criar
um array CuPy da API do NumPy, isso não é possível. Acho que seria
útil ter algo como:

importar numpy como np, cupy como cp
a = cp.array ([1, 2])
b = [1, 2]
c = np.asarray (b, like = a)

Alguma ideia / sugestão sobre isso?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/numpy/numpy/issues/13831?email_source=notifications&email_token=AAJJFVRCWDHRAXHHRDHXXM3P5H3LRA5CNFSM4H3HQWAKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODY57YVQ#issuecomment-507247702 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAJJFVRSYHUYHMPWQTW2NLLP5H3LRANCNFSM4H3HQWAA
.

np.copy_like parece bom. Eu concordo, provavelmente deveríamos ter maneiras de controlar coisas como dtype .

Desculpe pela pergunta do iniciante, mas algo como np.copy_like deveria ser uma emenda à NEP-22, deveria ser discutido na lista de discussão ou qual seria a abordagem mais apropriada para isso?

Na verdade, não temos regras rígidas sobre isso, mas gostaria de colocar np.copy_like e np.duckarray (ou o que quer que chamemos) juntos em um novo NEP sobre coagir / criar matrizes de pato, isso é prescritivo como NEP 18 em vez de "Informativo" como NEP 22. Não precisa ser longo, a maior parte da motivação já está clara com referência a NEP 18/22.

Uma nota sobre np.copy_like() : ele definitivamente deve despachar com __array_function__ (ou algo parecido), então operações como np.copy_like(sparse_array, like=dask_array) podem ser definidas em qualquer tipo de array.

Ótimo, obrigado pela informação e concordo com sua proposta de envio. Vou trabalhar em um NEP para a implementação de np.duckarray e np.copy_like e apresentar um esboço de PR esta semana para isso.

Incrível, obrigado Peter!

Na segunda-feira, 1º de julho de 2019 às 9h29 Peter Andreas Entschev <
notificaçõ[email protected]> escreveu:

Ótimo, obrigado pela informação e concordo com sua proposta de envio. Eu
trabalhará em um NEP para a implementação de np.duckarray e
np.copy_like e envie um rascunho de PR esta semana para isso.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/numpy/numpy/issues/13831?email_source=notifications&email_token=AAJJFVW2YUBNUCJZK6JWDBTP5IWHNA5CNFSM4H3HQWAKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODY6VM3Q#issuecomment-507336302 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAJJFVR2KTPAZ4JPWDYYMFLP5IWHNANCNFSM4H3HQWAA
.

O prazer, e muito obrigado pelas ideias e apoio com este trabalho!

As funções array_like e copy_like seriam um pouco estranhas de se ter no namespace principal, eu acho, já que não podemos ter uma implementação padrão (pelo menos não uma que faria o pensamento certo para cupy / dask / sparse / etc), certo? Eles só são úteis quando substituídos. Ou estou perdendo uma maneira de criar objetos de array não numpy arbitrários aqui?

É verdade, eles só seriam realmente úteis se você quiser oferecer suporte à digitação em pato. Mas certamente np.duckarray e np.copy_like funcionariam mesmo se os argumentos fossem apenas arrays NumPy - eles seriam apenas equivalentes a np.array / np.copy .

Todas as implementações de array têm um método copy , certo? Usar isso em vez de copy_like deve funcionar, então por que adicionar uma nova função?

array_like Posso ver a necessidade de, mas podemos querer discutir onde colocá-lo.

np.duckarray faz sentido para mim.

Gostaria de colocar np.copy_like e np.duckarray (ou como quer que chamemos) juntos em um novo NEP sobre coagir / criar matrizes de pato, um que é prescritivo como o NEP 18 em vez de "Informativo" como o NEP 22.

+1

array_like, posso ver a necessidade de, mas podemos querer discutir onde colocá-lo.

Esse é realmente o caso que eu gostaria de abordar com algo como np.copy_like . Não testei, mas provavelmente np.copy já despacha corretamente se o array não for NumPy.

Só para ficar claro, você está se referindo também a uma função np.array_like ? Evitei intencionalmente esse nome porque pensei que poderia confundir todas as referências existentes a array_like -arrays. No entanto, agora percebo que np.copy_like pode implicar uma cópia necessária, e acho que seria bom ter um comportamento semelhante a np.asarray , onde a cópia só acontece se já não for um NumPy array. No caso discutido aqui, o melhor seria fazer a cópia apenas se a não for do mesmo tipo que b em uma chamada como np.copy_like(a, like=b) .

Não testei, mas provavelmente np.copy já despacha corretamente se o array não for NumPy.

Deveria, está decorado para suportar __array_function__ .

Só para ficar claro, você está se referindo também a uma função np.array_like ? Evitei intencionalmente esse nome porque pensei que poderia confundir todas as referências existentes a array_like-arrays.

Sim. E sim, concordo que pode ser confuso.

No entanto, agora percebo que np.copy_like pode implicar em uma cópia necessária,

Sim, esse nome implica uma cópia de dados.

pode implicar em uma cópia necessária, e acho que seria bom ter um comportamento semelhante a np.asarray ,

Achei que fosse np.duckarray .

Acho que o exemplo de Peter acima pode ajudar a esclarecer isso. Copiado abaixo e legendado em np.copy_like para simplificar.

import numpy as np, cupy as cp
a  = cp.array([1, 2])
b = [1, 2]
c = np.copy_like(b, like=a)

Achei que fosse np.duckarray.

Na verdade, np.duckarray basicamente não fará nada e apenas retornará o próprio array (se sobrescrito), senão retornará np.asarray (levando a um array NumPy). Não podemos obter um array CuPy de uma lista Python com ele, por exemplo. Ainda precisamos de uma função que possa ser enviada para CuPy (ou qualquer outro array like= ) para um array_like .

Obrigado @jakirkham pelo exemplo atualizado.

c = np.copy_like(b, like=a)

Então, isso vai despachar para CuPy via a.__array_function__ e falhar se esse atributo não existir (por exemplo, a=<scipy.sparse matrix> não funcionaria)? Parece que precisamos de um novo namespace ou novo pacote de utilitários de interoperabilidade para esse tipo de coisa. Isso ou deixar para um mecanismo de despacho futuro mais completo, onde se poderia fazer simplesmente:

with cupy_backend:
   np.array(b)

A introdução de novas funções no namespace principal que não fazem sentido para o NumPy em si oferecer suporte para contornar uma limitação de __array_function__ parece um pouco insalubre ....

Então, isso irá despachar para CuPy via a.__array_function__ e falhar se esse atributo não existir (por exemplo, a=<scipy.sparse matrix> não funcionaria)?

Eu não diria que tem que falhar necessariamente. Poderíamos usar NumPy como padrão e emitir um aviso (ou não aumentá-lo), por exemplo.

Parece que precisamos de um novo namespace ou novo pacote de utilitários de interoperabilidade para esse tipo de coisa. Ou isso ou deixe para um mecanismo de despacho futuro mais completo

Certamente seria bom ter um mecanismo de despacho completo, mas imagino que isso não tenha sido feito antes devido à sua complexidade e problemas de compatibilidade com versões anteriores. Eu não estava por perto quando as discussões aconteceram, então apenas adivinhando.

A introdução de novas funções no namespace principal que não fazem sentido para o NumPy em si dar suporte para contornar uma limitação de __array_function__ parece um pouco insalubre ....

Eu certamente entendo seu ponto, mas também acho que se movermos muitas coisas para longe do namespace principal, isso pode assustar os usuários. Talvez eu esteja errado e isso seja apenas uma impressão. De qualquer forma, não estou propondo implementar funções que não funcionem com o NumPy, mas talvez não sejam absolutamente necessárias ao usar o NumPy sozinho.

A introdução de novas funções no namespace principal que não fazem sentido para o NumPy em si dar suporte para contornar uma limitação de __array_function__ parece um pouco insalubre ....

Na verdade, neste sentido, também np.duckarray não pertenceria ao namespace principal.

Na verdade, neste sentido, também np.duckarray não pertenceria ao namespace principal.

Acho que um é mais defensável (análogo a asarray e basicamente marcaria "isso atende à nossa definição de tipo de pato parecido com ndarray"), mas sim. Se também quisermos expor array_function_dispatch , e tivermos coisas np.lib.mixins.NDArrayOperatorsMixin e planejamos escrever mais mixins, um novo submódulo sensato para todas as coisas relacionadas à interoperabilidade poderia fazer sentido.

Certamente seria bom ter um mecanismo de despacho completo, mas imagino que isso não tenha sido feito antes devido à sua complexidade e problemas de compatibilidade com versões anteriores. Eu não estava por perto quando as discussões aconteceram, então apenas adivinhando.

Acho que há vários motivos. __array_function__ é semelhante a coisas que já tínhamos, por isso é mais fácil raciocinar. Possui baixa sobrecarga. Ele poderia ser projetado e implementado em uma escala de tempo de aproximadamente 6 meses, e @shoyer argumentou fortemente que precisávamos disso. E não tínhamos alternativa concreta.

Um novo submódulo sensato para todas as coisas relacionadas à interoperabilidade pode fazer sentido.

Sem objeções reais de mim, acho melhor ter funcionalidade em algum lugar do que em lugar nenhum. :)

Acho que há vários motivos. __array_function__ é semelhante a coisas que já tínhamos, então é mais fácil de raciocinar. Possui baixa sobrecarga. Ele poderia ser projetado e implementado em uma escala de tempo de aproximadamente 6 meses, e @shoyer argumentou fortemente que precisávamos disso. E não tínhamos alternativa concreta.

Mas se quisermos alavancar __array_function__ mais amplamente, temos outras alternativas agora para implementar coisas como np.duckarray e np.copy_like (ou qualquer outra coisa que decidiríamos chamá-lo)? Estou aberto a todas as alternativas, mas agora não vejo nenhuma, é claro, em vez de usar o modo de envio de recursos completos, o que provavelmente vai demorar muito e limitar o escopo de __array_function__ tremendamente (e basicamente tornando-o impraticável para a maioria dos casos mais complexos que já vi).

Mas se quisermos alavancar __array_function__ mais amplamente, temos outras alternativas agora para implementar coisas como np.duckarray e np.copy_like (ou qualquer outra coisa que decidiríamos chamá-lo)?

Eu acho que você realmente precisa de um conjunto de recursos de utilitários como esse, para ir da cobertura de uma fração de casos de uso para> 80% dos casos de uso. Não acho que haja uma maneira de contornar isso. Só não gosto de bagunçar o namespace principal, então proponho encontrar um lugar melhor para eles.

Estou aberto a todas as alternativas, mas agora não vejo nenhuma, é claro, em vez de usar o modo de envio de recursos completos, o que provavelmente vai demorar muito e limitar o escopo de __array_function__ tremendamente (e basicamente tornando-o impraticável para a maioria dos casos mais complexos que já vi).

Quer dizer, estamos apenas tapando alguns buracos óbvios aqui, certo? Nunca vamos cobrir todos os "casos mais complexos". Digamos que você queira substituir np.errstate ou np.dtype , isso simplesmente não vai acontecer com a abordagem baseada em protocolo.

Quanto às alternativas, o uarray ainda não está lá e ainda não estou convencido de que a sobrecarga será reduzida o suficiente para ser usada por padrão no NumPy, mas está chegando perto e estamos prestes a tentar criar o scipy.fft sistema de back-end (WIP PR: https://github.com/scipy/scipy/pull/10383). Se isso for comprovado lá, deve ser considerado como uma solução completa de despacho múltiplo. E já tem uma API numpy com back-ends Dask / Sparse / CuPy / PyTorch / XND, alguns dos quais são completos o suficiente para serem utilizáveis: https://github.com/Quansight-Labs/uarray/tree/master/unumpy

A abordagem de despacho com uarray é certamente interessante. Embora eu ainda esteja preocupado com a forma como lidamos com meta-arrays (como Dask, xarray, etc.). Por favor, veja este comentário para detalhes. Não está claro se isso foi resolvido (embora, por favor, corrija-me se eu tiver esquecido alguma coisa). Eu estaria interessado em trabalhar com outras pessoas na SciPy para tentar descobrir como podemos resolver esse problema.

Por favor, veja este comentário para detalhes. Não está claro se isso foi resolvido (embora, por favor, corrija-me se eu tiver esquecido alguma coisa).

Acho que as mudanças da semana passada resolveram isso, mas não tenho certeza - vamos deixar isso para outro tópico.

Eu estaria interessado em trabalhar com outras pessoas na SciPy para tentar descobrir como podemos resolver esse problema.

Eu estarei lá, seria ótimo conhecê-lo pessoalmente.

Talvez np.coerce_like() ou np.cast_like() sejam nomes melhores do que copy_like , de modo que fica claro que as cópias não são necessariamente necessárias. A funcionalidade desejada é de fato muito semelhante ao método .cast() , exceto que queremos converter tipos de array, bem como dtypes, e deve ser uma função em vez de um protocolo para que possa ser implementado por qualquer um dos argumentos.

A abordagem de despacho com uarray é certamente interessante. Embora eu ainda esteja preocupado com a forma como lidamos com meta-arrays (como Dask, xarray, etc.).

uarray tem suporte para vários back-ends, então algo como este deve funcionar

with ua.set_backend(inner_array_backend), ua.set_backend(outer_array_backend):
  s = unumpy.sum(meta_array)

Isso pode ser feito fazendo com que o meta-array chame ua.skip_backend dentro de sua implementação, ou se o backend do meta-array retornar NotImplemented na incompatibilidade de tipo.

cc: @hameerabbasi

Vou expandir isso: Como regra geral, para dask.array , qualquer coisa com da seria escrita sem um skip_backend. Qualquer coisa com NumPy precisaria de um skip_backend.

Ou por da você sempre pode pular o envio e chamar sua própria implementação diretamente e ter skip_backend(dask.array) todos os lugares.

Quanto a despachar funções que não têm um array anexado, como ones , cast , você apenas configuraria um back-end e pronto. O mesmo vale para np.errstate e np.dtype . Há um exemplo que cobre np.ufunc em unumpy .

Quanto ao problema original, uarray fornece o protocolo __ua_convert__ , que faz exatamente isso. Uma alternativa seria que os back-ends substituíssem asarray diretamente.

Obrigado pelo aviso sobre uarray , @rgommers , @ peterbell10 , @hameerabbasi.

Mas, como vejo, você _deve_ definir o back-end adequado antes de iniciar a computação, correto? Uma das vantagens de __array_function__ é que as bibliotecas podem ser totalmente independentes de outras bibliotecas, como o Dask não precisa saber da existência do CuPy, por exemplo.

@pentschev Esse era o caso até recentemente, quando adicionamos a capacidade de “registrar” um back-end, mas recomendamos que apenas o NumPy (ou uma implementação de referência) faça isso. Então, os usuários que usam Dask precisam apenas de um único set_backend.

Entendi, acho que foi isso que @rgommers mencionou em https://github.com/numpy/numpy/issues/13831#issuecomment -507432311, apontando para os back-ends em https://github.com/Quansight-Labs/uarray / tree / master / unumpy.

Desculpe por tantas perguntas, mas e se algum aplicativo hipotético depender de vários back-ends, por exemplo, NumPy e Sparse, onde dependendo da entrada do usuário, talvez tudo seja apenas NumPy, apenas Sparse ou uma mistura de ambos. @ peterbell10 mencionou que vários back-ends são suportados https://github.com/numpy/numpy/issues/13831#issuecomment -507458331, mas a seleção do back-end pode ser automática ou haveria necessidade de lidar com os três casos separadamente?

Portanto, para este caso, você idealmente registraria NumPy, usaria um gerenciador de contexto para Sparse e retornaria NotImplemented de esparso quando apropriado, o que faria algo retornar para NumPy.

Na SciPy, @rgommers , @danielballan e eu conversamos sobre esse problema. Concluímos que seria valioso continuar adicionando duckarray (usando esse nome). Dito isso, parecia que isso seria previsto para 1.18. Embora, por favor, me corrija se eu entendi mal as coisas. Diante disso, estaria tudo bem em começar um PR?

Concluímos que seria valioso continuar adicionando duckarray (usando esse nome). Dito isso, parecia que isso seria previsto para 1.18. Embora, por favor, me corrija se eu entendi mal as coisas. Diante disso, estaria tudo bem em começar um PR?

Tudo isso parece ótimo para mim, mas seria bom começar com um breve NEP explicando a proposta exata. Consulte https://github.com/numpy/numpy/issues/13831#issuecomment -507334210

Claro que faz sentido. 🙂

Quanto ao ponto de cópia que foi levantado anteriormente, estou curioso para saber se isso não é resolvido através dos mecanismos existentes. Em particular, e quanto a essas linhas?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Admitidamente, seria bom reduzir isso a uma linha. Só estou curioso para saber se isso já funciona para esse caso de uso ou se estão faltando coisas.

Concluímos que seria valioso continuar com a adição de duckarray (usando esse nome).

Tudo isso parece ótimo para mim, mas seria bom começar com um breve NEP explicando a proposta exata. Ver # 13831 (comentário)

Já comecei a escrever isso, mas ainda não fui capaz de concluí-lo (desculpe pelo meu mau planejamento https://github.com/numpy/numpy/issues/13831#issuecomment-507336302).

Quanto ao ponto de cópia que foi levantado anteriormente, estou curioso para saber se isso não é resolvido através dos mecanismos existentes. Em particular, e quanto a essas linhas?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Admitidamente, seria bom reduzir isso a uma linha. Só estou curioso para saber se isso já funciona para esse caso de uso ou se estão faltando coisas.

Você pode fazer isso, mas pode exigir uma lógica de cópia especial (como em CuPy https://github.com/cupy/cupy/pull/2079).

Dito isso, uma função de cópia pode ser melhor, para evitar que esse código adicional de classificação seja necessário.

Por outro lado, isso seria uma espécie de substituição para asarray . Então, eu queria saber se, em vez de alguma função copy_like nova, gostaríamos de revisar a ideia sugerida pela NEP-18 :

Eles precisarão de seus próprios protocolos:
...
array e asarray, porque se destinam explicitamente à coerção do objeto numpy.ndarray real.

Se houver uma chance de que gostemos de revisitar isso, talvez seja melhor começar um novo tópico. Alguma ideia, sugestão, objeção?

Só para ficar claro no meu comentário acima, eu mesmo não sei se um novo protocolo é uma ótima ideia (provavelmente muitos detalhes incômodos que não prevejo estão envolvidos), na verdade só me pergunto se essa é uma ideia que devemos revisitar e discutir .

O consenso da reunião de desenvolvimento e sprint na SciPy'19 foi: vamos lançar o 1.17.0 e obter alguma experiência do mundo real com ele antes de dar os próximos passos.

na verdade, apenas nos perguntando se essa é uma ideia que devemos revisitar e discutir.

provavelmente sim, mas em alguns meses.

provavelmente sim, mas em alguns meses.

Ok, obrigado pela resposta!

Quanto ao ponto de cópia que foi levantado anteriormente, estou curioso para saber se isso não é resolvido através dos mecanismos existentes. Em particular, e quanto a essas linhas?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Admitidamente, seria bom reduzir isso a uma linha. Só estou curioso para saber se isso já funciona para esse caso de uso ou se estão faltando coisas.

Meu principal problema com isso é que não funcionaria para matrizes de pato imutáveis, o que não é terrivelmente incomum. Além disso, para NumPy, o custo adicional de alocar uma matriz e preenchê-la pode ser quase zero, mas não tenho certeza se isso é verdade para todas as matrizes de pato.

Quanto ao ponto de cópia que foi levantado anteriormente, estou curioso para saber se isso não é resolvido através dos mecanismos existentes. Em particular, e quanto a essas linhas?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Admitidamente, seria bom reduzir isso a uma linha. Só estou curioso para saber se isso já funciona para esse caso de uso ou se estão faltando coisas.

Você pode fazer isso, mas pode exigir uma lógica de cópia especial (como em CuPy cupy / cupy # 2079 ).

Dito isso, uma função de cópia pode ser melhor, para evitar que esse código adicional de classificação seja necessário.

Por outro lado, isso seria uma espécie de substituição para asarray . Então, eu queria saber se, em vez de alguma função copy_like nova, gostaríamos de revisar a ideia sugerida pela NEP-18 :

Eles precisarão de seus próprios protocolos:
...
array e asarray, porque se destinam explicitamente à coerção do objeto numpy.ndarray real.

Se houver uma chance de que gostemos de revisitar isso, talvez seja melhor começar um novo tópico. Alguma ideia, sugestão, objeção?

Não acho uma boa ideia alterar o comportamento de np.array ou np.asarray com um novo protocolo. Seu significado estabelecido é lançar em matrizes NumPy, que é basicamente por que precisamos de np.duckarray

Dito isso, podemos considerar a adição de um argumento like a duckarray . Isso exigiria alterar o protocolo da proposta simplificada acima - talvez usar __array_function__ vez de um protocolo dedicado como __duckarray__ ? Eu realmente não pensei sobre isso.

Quanto ao ponto de cópia que foi levantado anteriormente, estou curioso para saber se isso não é resolvido através dos mecanismos existentes. Em particular, e quanto a essas linhas?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Admitidamente, seria bom reduzir isso a uma linha. Só estou curioso para saber se isso já funciona para esse caso de uso ou se estão faltando coisas.

Meu principal problema com isso é que não funcionaria para matrizes de pato imutáveis, o que não é terrivelmente incomum. Além disso, para NumPy, o custo adicional de alocar uma matriz e preenchê-la pode ser quase zero, mas não tenho certeza se isso é verdade para todas as matrizes de pato.

Isso é justo. Na verdade, já podemos simplificar as coisas. Por exemplo, isso funciona com CuPy e Sparse hoje.

a2 = np.copy(a1)

Isso é justo. Na verdade, já podemos simplificar as coisas. Por exemplo, isso funciona com CuPy e Sparse hoje.

a2 = np.copy(a1)

Sim, mas também queremos "copiar esta matriz de pato no tipo desta outra matriz de pato"

Não acho uma boa ideia mudar o comportamento de np.array ou np.asarray com um novo protocolo. Seu significado estabelecido é lançar em matrizes NumPy, que é basicamente porque precisamos de np.duckarray

Também estou inseguro quanto a isso, e relutava até em levantar essa questão, é por isso que não o fiz até hoje.

Dito isso, podemos considerar a adição de um argumento similar ao duckarray. Isso exigiria alterar o protocolo da proposta simplificada acima - talvez usar __array_function__ em vez de um protocolo dedicado como __duckarray__? Eu realmente não pensei sobre isso.

Não sei se haveria complicações com isso, provavelmente precisamos de algum cuidado, mas tendo a gostar dessa ideia. Isso pareceria redundante em vários níveis, mas talvez para seguir o padrão existente, em vez de adicionar um parâmetro like , poderíamos ter duckarray e duckarray_like ?

Sim, mas também queremos "copiar esta matriz de pato no tipo desta outra matriz de pato"

Que tal basear isso em np.copyto ?

Que tal basear isso em np.copyto ?

Sinta-se à vontade para me corrigir se eu estiver errado, mas presumo que você queira dizer algo como:

np.copyto(cupy_array, numpy_array)

Isso poderia funcionar, assumindo que NumPy está disposto a mudar o comportamento atual, por exemplo, asarray sempre implica que o destino é um array NumPy, copyto faz a mesma suposição?

np.copyto já suporta o envio com __array_function__ , mas é aproximadamente equivalente a:

def copyto(dst, src):
    dst[...] = src

Queremos o equivalente a:

def copylike(src, like):
    dst = np.empty_like(like)
    dst[...] = src
    return dst

np.copyto já suporta o envio com __array_function__ , mas é aproximadamente equivalente a:

def copyto(dst, src):
    dst[...] = src

Queremos o equivalente a:

def copylike(src, like):
    dst = np.empty_like(like)
    dst[...] = src
    return dst

Correto, é isso que queremos. copyto é despachado e funciona se a origem e o destino forem do mesmo tipo, precisamos de algo que permita o despacho para a biblioteca do array de destino.

Bem, copyto ainda pode fazer sentido, dependendo de como pensamos a respeito. Veja, por exemplo, o seguinte caso de uso.

np.copyto(cp.ndarray, np.random.random((3,)))

Isso pode se traduzir em algo como alocar e copiar os dados, conforme discutimos. Se distribuirmos cerca de dst ( cp.ndarray neste caso), então as bibliotecas com matrizes imutáveis ​​também podem implementar isso de maneira adequada. Isso também nos evita de adicionar uma nova API (que o NumPy apenas fornece, mas não usa), o que parecia ser uma preocupação.

Apenas para trazer à tona outro pensamento que me ocorreu recentemente, vale a pena pensar sobre o que essas APIs significarão no downstream entre outras bibliotecas (por exemplo, como Dask e Xarray interagem).

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

Questões relacionadas

inducer picture inducer  ·  3Comentários

manuels picture manuels  ·  3Comentários

ghost picture ghost  ·  4Comentários

dmvianna picture dmvianna  ·  4Comentários

navytux picture navytux  ·  4Comentários