Capítulo 11, Básico
Reshape e transposição
Os mesmos dados, em outra forma. Quase toda função de biblioteca espera uma forma específica, e remodelar é como você a entrega.
Código deste capítulo: básico/cap11_reshape.py
Remodelar sem mexer nos dados
O reshape reorganiza os mesmos elementos em outra forma. O total precisa continuar o mesmo: ele nunca cria nem remove elementos. E o -1 em uma das dimensões significa "calcule você":
import numpy as np
arr = np.arange(12)
print(arr.reshape(3, 4))
print(arr.reshape(2, -1).shape, arr.reshape(-1, 3).shape)
try:
arr.reshape(5, 3)
except ValueError as erro:
print(erro)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
(2, 6) (4, 3)
cannot reshape array of size 12 into shape (5,3)
Cinco vezes três dá 15, e o array tem 12 elementos, então o NumPy recusa. O reshape(2, -1) descobriu sozinho que a segunda dimensão é 6.
Transpor, achatar e inserir eixos
grade = np.arange(6).reshape(2, 3)
print(grade.T.shape, grade.transpose().shape)
print(grade.flatten(), grade.ravel())
print(grade[:, np.newaxis, :].shape, grade[..., None].shape)
print(np.squeeze(np.zeros((1, 3, 1))).shape)
(3, 2) (3, 2)
[0 1 2 3 4 5] [0 1 2 3 4 5]
(2, 1, 3) (2, 3, 1)
(3,)
| Função | O que faz |
|---|---|
a.T ou a.transpose() | Troca linhas e colunas. Em mais dimensões, inverte a ordem dos eixos |
a.swapaxes(i, j) | Troca dois eixos específicos |
a.flatten() | Achata para 1D e sempre copia |
a.ravel() | Achata para 1D e devolve uma view quando possível |
np.newaxis ou None | Insere um eixo de tamanho 1 |
np.squeeze(a) | Remove os eixos de tamanho 1 |
A diferença entre flatten e ravel é a mesma do capítulo anterior: um copia, o outro compartilha memória, e alterar o resultado do ravel muda o original:
r = grade.ravel()
r[0] = 99
print(grade[0, 0])
f = grade.flatten()
f[0] = -1
print(grade[0, 0])
99
99
O truque do eixo extra
Inserir um eixo de tamanho 1 é a forma de preparar um vetor para o broadcasting do próximo capítulo. Um vetor de forma (3,) vira uma coluna (3, 1) com reshape(-1, 1) ou com [:, None]:
vetor = np.array([1, 2, 3])
print(vetor.reshape(-1, 1))
[[1]
[2]
[3]]
Um caso real: lote de imagens
Um lote de 10 imagens de 28 por 28 pixels tem forma (10, 28, 28). Muitos modelos esperam cada imagem como um vetor de 784 números, ou seja, forma (10, 784). O -1 calcula o 784 sozinho:
lote = np.zeros((10, 28, 28))
print(lote.reshape(10, -1).shape)
(10, 784)
reshape devolve view quando pode
O
reshapedevolve uma view se a memória permitir e só copia quando não há outro jeito. Por isso, depois de umreshape, tenha em mente que alterar o resultado pode alterar o original. Em dúvida, confira comnp.shares_memory.
Exercício 1
Coluna e planilha
Escreva para_coluna(v) (um vetor 1D vira uma coluna) e lote_para_planilha(imagens) (de (n, h, w) para (n, h*w)).