Em numpy
, algumas das operações retornam em forma, (R, 1)
mas algumas retornam (R,)
. Isso tornará a multiplicação de matrizes mais tediosa, pois reshape
é necessário explícito . Por exemplo, dada uma matriz M
, se queremos fazer numpy.dot(M[:,0], numpy.ones((1, R)))
onde R
está o número de linhas (é claro, o mesmo problema também ocorre em colunas). Iremos receber um matrices are not aligned
erro, pois M[:,0]
está em forma, (R,)
mas numpy.ones((1, R))
está em forma (1, R)
.
Então, minhas perguntas são:
Qual é a diferença entre shape
(R, 1)
e(R,)
. Eu sei literalmente que é lista de números e lista de listas onde toda a lista contém apenas um número. Apenas me pergunto por que não projetarnumpy
para favorecer a forma em(R, 1)
vez de(R,)
facilitar a multiplicação da matriz.Existem maneiras melhores para o exemplo acima? Sem remodelar explicitamente assim:
numpy.dot(M[:,0].reshape(R, 1), numpy.ones((1, R)))
Respostas:
1. O significado das formas no NumPy
Você escreve: "Eu sei literalmente que é uma lista de números e uma lista de listas em que toda a lista contém apenas um número", mas essa é uma maneira inútil de pensar sobre isso.
A melhor maneira de pensar sobre matrizes NumPy é que elas consistem em duas partes, um buffer de dados que é apenas um bloco de elementos brutos e uma exibição que descreve como interpretar o buffer de dados.
Por exemplo, se criarmos uma matriz de 12 números inteiros:
Em seguida,
a
consiste em um buffer de dados, organizado assim:e uma visão que descreve como interpretar os dados:
Aqui, a forma
(12,)
significa que a matriz é indexada por um único índice, que varia de 0 a 11. Conceitualmente, se rotularmos esse único índicei
, a matriz terá a seguintea
aparência:Se remodelarmos uma matriz, isso não altera o buffer de dados. Em vez disso, ele cria uma nova exibição que descreve uma maneira diferente de interpretar os dados. Então depois:
a matriz
b
possui o mesmo buffer de dados quea
, mas agora é indexada por dois índices que variam de 0 a 2 e 0 a 3, respectivamente. Se rotularmos os dois índicesi
ej
, a matriz seráb
assim:o que significa que:
Você pode ver que o segundo índice muda rapidamente e o primeiro índice muda lentamente. Se você preferir que isso seja o contrário, você pode especificar o
order
parâmetro:o que resulta em uma matriz indexada assim:
o que significa que:
Agora deve ficar claro o que significa para uma matriz ter uma forma com uma ou mais dimensões de tamanho 1. Depois:
a matriz
d
é indexada por dois índices, o primeiro dos quais é executado de 0 a 11 e o segundo índice é sempre 0:e entao:
Uma dimensão de comprimento 1 é "livre" (em certo sentido), então não há nada que o impeça de ir à cidade:
dando uma matriz indexada assim:
e entao:
Consulte a documentação interna do NumPy para obter mais detalhes sobre como as matrizes são implementadas.
2. O que fazer?
Como
numpy.reshape
apenas cria uma nova exibição, você não deve ter medo de usá-la sempre que necessário. É a ferramenta certa a ser usada quando você deseja indexar uma matriz de uma maneira diferente.No entanto, em um cálculo longo, geralmente é possível organizar matrizes com a forma "correta" em primeiro lugar e, assim, minimizar o número de remodelações e transposições. Mas sem ver o contexto real que levou à necessidade de uma remodelação, é difícil dizer o que deve ser mudado.
O exemplo na sua pergunta é:
mas isso não é realista. Primeiro, esta expressão:
calcula o resultado de maneira mais simples. Segundo, há realmente algo de especial na coluna 0? Talvez o que você realmente precise seja:
fonte
newaxis
se você precisar de outro eixo, por exemplo,a[:, j, np.newaxis]
é aj
th coluna dea
ea[np.newaxis, i]
é ai
th row.(R, )
caso, a forma dondarray
é uma tupla com um único elemento; portanto, é impressa pelo Python com uma vírgula à direita. Sem a vírgula extra, seria ambíguo com uma expressão entre parênteses . Umndarray
com uma única dimensão pode ser considerado como um vetor de comprimento de colunaR
. No(R, 1)
caso, o tuplo tem dois elementos, por isso podem ser consideradas como um vector da linha (ou uma matriz com uma linha de comprimentoR
.A diferença entre
(R,)
e(1,R)
é literalmente o número de índices que você precisa usar.ones((1,R))
é uma matriz 2D que possui apenas uma linha.ones(R)
é um vetor. Geralmente, se não faz sentido que a variável tenha mais de uma linha / coluna, você deve usar um vetor, não uma matriz com uma dimensão singleton.Para o seu caso específico, existem algumas opções:
1) Apenas faça do segundo argumento um vetor. O seguinte funciona bem:
2) Se você deseja operações matlab como matriz, use a classe em
matrix
vez dendarray
. Todas as matrizes são forçadas a serem matrizes 2-D e o operador*
faz a multiplicação de matrizes em vez de elementos (por isso, não é necessário ponto). Na minha experiência, isso vale mais a pena, mas pode ser bom se você estiver acostumado com o matlab.fonte
matrix
aula. Qual é o problema damatrix
classe BTW?matrix
é que ele é apenas 2D e também porque sobrecarrega o operador '*', as funções escritas parandarray
podem falhar se usadas em amatrix
.A forma é uma tupla. Se houver apenas uma dimensão, a forma será um número e ficará em branco após uma vírgula. Para 2 ou mais dimensões, haverá um número depois de todas as vírgulas.
fonte
Para sua classe de matriz base, as matrizes 2d não são mais especiais que as 1d ou 3d. Existem operações que preservam as dimensões, outras que as reduzem, outras as combinam ou até as expandem.
Outras expressões que dão a mesma matriz
O MATLAB começou com apenas matrizes 2D. As versões mais recentes permitem mais dimensões, mas mantêm o limite inferior de 2. Mas você ainda precisa prestar atenção à diferença entre uma matriz de linhas e uma coluna, uma com a forma
(1,3)
v(3,1)
. Quantas vezes você escreveu[1,2,3].'
? Eu ia escreverrow vector
ecolumn vector
, mas com essa restrição 2D, não existem vetores no MATLAB - pelo menos não no sentido matemático do vetor como sendo 1d.Você já viu
np.atleast_2d
(também as versões _1d e _3d)?fonte
1) A razão para não preferir uma forma de
(R, 1)
excesso(R,)
é que ela complica desnecessariamente as coisas. Além disso, por que seria preferível ter forma(R, 1)
por padrão para um vetor comprimento-R em vez de(1, R)
? É melhor mantê-lo simples e ser explícito quando você precisar de dimensões adicionais.2) No seu exemplo, você está computando um produto externo para poder fazer isso sem uma
reshape
chamada usandonp.outer
:fonte
M[:,0]
está essencialmente obtendo todas as linhas com o primeiro elemento, por isso faz mais sentido ter do(R, 1)
que(1, R)
. 2) Nem sempre é substituível pornp.outer
, por exemplo, ponto para matriz em forma (1, R) e depois (R, 1).matrix
objeto. 2) Na verdade,np.outer
funciona independentemente do facto das formas são(1, R)
,(R, 1)
, ou uma combinação dos dois.Já existem muitas boas respostas aqui. Mas, para mim, foi difícil encontrar algum exemplo, onde a forma ou matriz possa quebrar todo o programa.
Então aqui está o seguinte:
Isso falhará com erro:
mas se adicionarmos
reshape
aa
:isso funciona corretamente!
fonte