Quais são as vantagens do NumPy em relação às listas regulares de Python?

466

Quais são as vantagens do NumPy em relação às listas regulares de Python?

Tenho aproximadamente 100 séries de mercados financeiros e vou criar uma matriz de cubos de 100x100x100 = 1 milhão de células. Estarei regredindo (3 variáveis) cada x com cada ye z, para preencher a matriz com erros padrão.

Ouvi dizer que, para "matrizes grandes", devo usar o NumPy em vez de listas Python, por razões de desempenho e escalabilidade. O problema é que eu sei as listas Python e elas parecem funcionar para mim.

Quais serão os benefícios se eu mudar para o NumPy?

E se eu tivesse 1000 séries (ou seja, 1 bilhão de células de ponto flutuante no cubo)?

Thomas Browne
fonte

Respostas:

727

As matrizes de NumPy são mais compactas que as listas Python - uma lista de listas que você descreve, em Python, levaria pelo menos 20 MB, enquanto uma matriz NumPy 3D com flutuadores de precisão única nas células caberia em 4 MB. O acesso aos itens de leitura e gravação também é mais rápido com o NumPy.

Talvez você não se importe muito com apenas um milhão de células, mas definitivamente se importaria com um bilhão de células - nenhuma abordagem se encaixaria em uma arquitetura de 32 bits, mas com compilações de 64 bits, o NumPy se safaria com 4 GB ou mais , Somente o Python precisaria de pelo menos 12 GB (muitos ponteiros que dobram de tamanho) - uma peça de hardware muito mais cara!

A diferença se deve principalmente à "indiretamente" - uma lista Python é uma matriz de ponteiros para objetos Python, pelo menos 4 bytes por ponteiro mais 16 bytes até para o menor objeto Python (4 para o tipo de ponteiro, 4 para a contagem de referência, 4 por valor - e os alocadores de memória arredondam para 16). Uma matriz NumPy é uma matriz de valores uniformes - os números de precisão única levam 4 bytes cada, os de precisão dupla, 8 bytes. Menos flexível, mas você paga substancialmente pela flexibilidade das listas Python padrão!

Alex Martelli
fonte
Eu tenho tentado usar "sys.getsizeof ()" para comparar o tamanho das listas Python e matrizes NumPy com o mesmo número de elementos e isso não parece indicar que as matrizes NumPy eram muito menores. É esse o caso ou o sys.getsizeof () está tendo problemas para descobrir qual o tamanho de uma matriz NumPy?
Jack Simpson
3
@JackSimpson getsizeofnão é confiável. A documentação afirma claramente que: Apenas o consumo de memória diretamente atribuído ao objeto é contabilizado, não o consumo de memória dos objetos a que se refere. Isso significa que, se você aninhar listas python, o tamanho dos elementos não é levado em consideração.
Bakuriu 9/08/16
4
getsizeofem uma lista, apenas informa a quantidade de RAM que o próprio objeto de lista consome e a RAM consumida pelos ponteiros em sua matriz de dados, não informa a quantidade de RAM consumida pelos objetos a que esses ponteiros se referem.
PM 2Ring
@AlexMartelli, você poderia me informar de onde está conseguindo esses números?
Lmiguelvargasf
Apenas um alerta, sua estimativa do tamanho da lista equivalente de listas de listas Python está desativada. A matriz numpy de 4 GB de C floats (4 bytes) se traduziria em algo mais próximo de 32 GB no valor de se listPython floats (que na verdade são C doubles), não de 12 GB; cada um floatem Python de 64 bits ocupa ~ 24 bytes (assumindo que não há perdas de alinhamento no alocador), mais outros 8 bytes listpara manter a referência (e isso ignora a localização geral e os cabeçalhos de objetos para listsi, o que pode adicionar outro GB dependendo exatamente quanto ocorre a superalocação).
ShadowRanger 8/18
232

NumPy não é apenas mais eficiente; também é mais conveniente. Você obtém muitas operações de vetores e matrizes de graça, o que às vezes permite evitar trabalhos desnecessários. E eles também são implementados com eficiência.

Por exemplo, você pode ler seu cubo diretamente de um arquivo em uma matriz:

x = numpy.fromfile(file=open("data"), dtype=float).reshape((100, 100, 100))

Soma ao longo da segunda dimensão:

s = x.sum(axis=1)

Encontre quais células estão acima de um limite:

(x > 0.5).nonzero()

Remova todas as fatias indexadas pares ao longo da terceira dimensão:

x[:, :, ::2]

Além disso, muitas bibliotecas úteis trabalham com matrizes NumPy. Por exemplo, análise estatística e bibliotecas de visualização.

Mesmo que você não tenha problemas de desempenho, aprender o NumPy vale a pena.

Roberto Bonvallet
fonte
Obrigado - você forneceu outro bom motivo no seu terceiro exemplo, pois, de fato, procurarei na matriz células acima do limite. Além disso, eu estava carregando do sqlLite. A abordagem de arquivo será muito mais eficiente.
9789 Thomas Thomase
112

Alex mencionou eficiência de memória e Roberto menciona conveniência, e esses são dois pontos positivos. Para mais algumas idéias, mencionarei velocidade e funcionalidade .

Funcionalidade: você incorpora muito o NumPy, FFTs, convoluções, pesquisa rápida, estatísticas básicas, álgebra linear, histogramas, etc. E realmente, quem pode viver sem FFTs?

Velocidade: aqui está um teste para fazer uma soma sobre uma lista e uma matriz NumPy, mostrando que a soma na matriz NumPy é 10x mais rápida (neste teste - a milhagem pode variar).

from numpy import arange
from timeit import Timer

Nelements = 10000
Ntimeits = 10000

x = arange(Nelements)
y = range(Nelements)

t_numpy = Timer("x.sum()", "from __main__ import x")
t_list = Timer("sum(y)", "from __main__ import y")
print("numpy: %.3e" % (t_numpy.timeit(Ntimeits)/Ntimeits,))
print("list:  %.3e" % (t_list.timeit(Ntimeits)/Ntimeits,))

que em meus sistemas (enquanto estou executando um backup) fornece:

numpy: 3.004e-05
list:  5.363e-04
tom10
fonte
44

Aqui está uma boa resposta das perguntas frequentes no site scipy.org :

Quais vantagens as matrizes NumPy oferecem sobre listas Python (aninhadas)?

As listas do Python são eficientes contêineres de uso geral. Eles suportam inserção, exclusão, exclusão e concatenação (razoavelmente) eficientes, e a compreensão da lista do Python facilita a construção e a manipulação. No entanto, eles têm certas limitações: eles não suportam operações "vetorizadas", como adição e multiplicação por elementos, e o fato de poderem conter objetos de tipos diferentes significa que o Python deve armazenar informações de tipo para cada elemento e executar o código de despacho de tipo ao operar em cada elemento. Isso também significa que pouquíssimas operações de lista podem ser executadas por loops C eficientes - cada iteração exigiria verificações de tipo e outra contabilidade da API do Python.

Eliezer
fonte
9

Todos destacaram quase todas as principais diferenças entre a matriz numpy e a lista python. Vou apresentá-las aqui:

  1. Matrizes numpy têm um tamanho fixo na criação, diferentemente das listas python (que podem crescer dinamicamente). Alterar o tamanho do ndarray criará uma nova matriz e excluirá o original.

  2. Todos os elementos em uma matriz Numpy precisam ter o mesmo tipo de dados (também podemos ter o tipo heterogêneo, mas isso não permitirá operações matemáticas) e, portanto, terão o mesmo tamanho na memória

  3. Matrizes numpy são avanços facilitados em matemática e outros tipos de operações em um grande número de dados. Normalmente, essas operações são executadas de forma mais eficiente e com menos código do que é possível usando pythons construídos em sequências

Parvez Khan
fonte